merging uni's branch. one bug appeared back

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/hilnius@13386 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hilnius 2013-07-30 00:41:47 +00:00
commit a20c200b77
94 changed files with 1555 additions and 1256 deletions

View File

@ -0,0 +1,23 @@
<stkgui>
<div x="2%" y="5%" width="96%" height="90%" layout="vertical-row" >
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
I18N="In the registration dialog' dialog" text="Account Recovery"/>
<spacer height="20" width="50">
<label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true" I18N="In the registration dialog"
text="You will receive an email with further instructions on how to reset your password. Please be patient and be sure to check your spam folder."/>
<spacer height="20" width="50">
<buttonbar id="options" width="25%" height="15%" align="center">
<icon-button id="cancel" width="64" height="64" icon="gui/green_check.png"
I18N="Registration dialog" text="Close" label_location="none"/>
</buttonbar>
</div>
</stkgui>

View File

@ -0,0 +1,46 @@
<stkgui>
<div x="2%" y="5%" width="96%" height="90%" layout="vertical-row" >
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
I18N="In the recovery dialog' dialog" text="Account Recovery"/>
<spacer height="20" width="50">
<label id="message" proportion="2" width="90%" align="center" text_align="left" word_wrap="true"
text="Fill in the username and email address you supplied at registration to be able to reset your password."/>
<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 recovery dialog" text="Username"/>
<textbox proportion="2" id="username" I18N="In the recovery dialog"/>
</div>
<spacer height="20" width="20">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the recovery dialog" text="Email"/>
<textbox proportion="2" id="email" I18N="In the recovery dialog"/>
</div>
</div>
<spacer height="20" width="50">
<label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true"
I18N="In the recovery" text=""/>
<spacer height="20" width="50">
<buttonbar id="options" width="25%" proportion="1" align="center">
<icon-button id="submit" width="64" height="64" icon="gui/green_check.png"
I18N="Registration dialog" text="Submit" 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>
</stkgui>

View File

@ -1,28 +0,0 @@
<stkgui>
<div x="2%" y="5%" width="96%" height="90%" layout="vertical-row" >
<header id="title" width="96%" proportion="1" text_align="center" word_wrap="true"
I18N="In the registration dialog' dialog" text="User Activation"/>
<spacer height="20" width="50">
<label id="terms" proportion="6" width="90%" align="center" text_align="center" word_wrap="true"
I18N="In the registration dialog' dialog" text="Activation information will come here."/>
<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="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>
</stkgui>

View File

@ -2,59 +2,21 @@
<div x="2%" y="5%" width="96%" height="90%" layout="vertical-row" > <div x="2%" y="5%" width="96%" height="90%" layout="vertical-row" >
<header id="title" width="96%" proportion="1" text_align="center" word_wrap="true" <header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
I18N="In the registration dialog' dialog" text="Registration"/> I18N="In the registration dialog' dialog" text="Registration Complete"/>
<spacer height="40" width="50"> <spacer height="20" width="50">
<div width="80%" align="center" layout="vertical-row" height="fit"> <label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true" I18N="In the registration dialog"
<div width="100%" height="fit" layout="horizontal-row" > text="You will receive an email with further instructions regarding account activation. Please be patient and be sure to check your spam folder."/>
<label proportion="1" text_align="left" I18N="In the registration dialog" text="Username"/>
<textbox proportion="2" id="username" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the registration dialog" text="Password"/>
<textbox proportion="2" id="password" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the registration dialog" text="Confirm"/>
<textbox proportion="2" id="password_confirm" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the registration dialog" text="Email"/>
<textbox proportion="2" id="email" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the registration dialog" text="Confirm"/>
<textbox proportion="2" id="email_confirm" I18N="In the registration dialog"/>
</div>
</div>
<spacer height="20" width="50">
<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"> <spacer height="20" width="50">
<buttonbar id="options" width="25%" proportion="1" align="center"> <buttonbar id="options" width="25%" height="15%" align="center">
<icon-button id="next" width="64" height="64" icon="gui/green_check.png" <icon-button id="cancel" width="64" height="64" icon="gui/green_check.png"
I18N="Registration dialog" text="Next" label_location="none"/> I18N="Registration dialog" text="Close" 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> </buttonbar>
</div> </div>

View File

@ -0,0 +1,61 @@
<stkgui>
<div x="2%" y="5%" width="96%" height="90%" layout="vertical-row" >
<header id="title" width="96%" proportion="1" text_align="center" word_wrap="true"
I18N="In the registration dialog' dialog" text="Registration"/>
<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 registration dialog" text="Username"/>
<textbox proportion="2" id="username" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the registration dialog" text="Password"/>
<textbox proportion="2" id="password" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the registration dialog" text="Confirm"/>
<textbox proportion="2" id="password_confirm" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the registration dialog" text="Email"/>
<textbox proportion="2" id="email" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the registration dialog" text="Confirm"/>
<textbox proportion="2" id="email_confirm" I18N="In the registration dialog"/>
</div>
</div>
<spacer height="20" width="50">
<label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true"
I18N="In the registration dialog" text="You don't need to register if you have a STK Addons account!"/>
<spacer height="20" width="50">
<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>
</stkgui>

View File

@ -19,7 +19,7 @@
<spacer height="20" width="50"> <spacer height="20" width="50">
<label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true" <label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true"
I18N="In the registration dialog' dialog" text=""/> I18N="In the registration dialog" text=""/>
<spacer height="20" width="50"> <spacer height="20" width="50">

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -147,6 +147,12 @@
<camera distance="1.5" forward-up-angle="15" <camera distance="1.5" forward-up-angle="15"
backward-up-angle="30"/> backward-up-angle="30"/>
<!-- Jump animation related values:
animation-time: only if the estimated time for a jump is larger
than this value will the jump animation being
shown. -->
<jump animation-time="0.5" />
<!-- If a kart starts within the specified time after 'go', <!-- If a kart starts within the specified time after 'go',
it receives the corresponding bonus from 'boost'. Those it receives the corresponding bonus from 'boost'. Those
fields must have the same size, and must be sorted by fields must have the same size, and must be sorted by

View File

@ -209,6 +209,7 @@ src/states_screens/dialogs/message_dialog.cpp
src/states_screens/dialogs/player_info_dialog.cpp src/states_screens/dialogs/player_info_dialog.cpp
src/states_screens/dialogs/press_a_key_dialog.cpp src/states_screens/dialogs/press_a_key_dialog.cpp
src/states_screens/dialogs/race_paused_dialog.cpp src/states_screens/dialogs/race_paused_dialog.cpp
src/states_screens/dialogs/recovery_dialog.cpp
src/states_screens/dialogs/registration_dialog.cpp src/states_screens/dialogs/registration_dialog.cpp
src/states_screens/dialogs/select_challenge.cpp src/states_screens/dialogs/select_challenge.cpp
src/states_screens/dialogs/server_info_dialog.cpp src/states_screens/dialogs/server_info_dialog.cpp
@ -503,6 +504,7 @@ src/states_screens/dialogs/message_dialog.hpp
src/states_screens/dialogs/player_info_dialog.hpp src/states_screens/dialogs/player_info_dialog.hpp
src/states_screens/dialogs/press_a_key_dialog.hpp src/states_screens/dialogs/press_a_key_dialog.hpp
src/states_screens/dialogs/race_paused_dialog.hpp src/states_screens/dialogs/race_paused_dialog.hpp
src/states_screens/dialogs/recovery_dialog.hpp
src/states_screens/dialogs/registration_dialog.hpp src/states_screens/dialogs/registration_dialog.hpp
src/states_screens/dialogs/select_challenge.hpp src/states_screens/dialogs/select_challenge.hpp
src/states_screens/dialogs/server_info_dialog.hpp src/states_screens/dialogs/server_info_dialog.hpp

View File

@ -1266,23 +1266,6 @@ void IrrDriver::displayFPS()
const int NO_TRUST_COUNT = 200; const int NO_TRUST_COUNT = 200;
static int no_trust = NO_TRUST_COUNT; static int no_trust = NO_TRUST_COUNT;
if (no_trust)
{
no_trust--;
static video::SColor fpsColor = video::SColor(255, 255, 0, 0);
font->draw( L"FPS: ...", core::rect< s32 >(100,0,400,50), fpsColor,
false );
return;
}
// Ask for current frames per second and last number of triangles
// processed (trimed to thousands)
const int fps = m_video_driver->getFPS();
const float kilotris = m_video_driver->getPrimitiveCountDrawn(0)
* (1.f / 1000.f);
// Min and max info tracking, per mode, so user can check game vs menus // Min and max info tracking, per mode, so user can check game vs menus
bool current_state = StateManager::get()->getGameState() bool current_state = StateManager::get()->getGameState()
== GUIEngine::GAME; == GUIEngine::GAME;
@ -1303,6 +1286,23 @@ void IrrDriver::displayFPS()
prev_state = current_state; prev_state = current_state;
} }
if (no_trust)
{
no_trust--;
static video::SColor fpsColor = video::SColor(255, 255, 0, 0);
font->draw( L"FPS: ...", core::rect< s32 >(100,0,400,50), fpsColor,
false );
return;
}
// Ask for current frames per second and last number of triangles
// processed (trimed to thousands)
const int fps = m_video_driver->getFPS();
const float kilotris = m_video_driver->getPrimitiveCountDrawn(0)
* (1.f / 1000.f);
if (min > fps && fps > 1) min = fps; // Start moments sometimes give useless 1 if (min > fps && fps > 1) min = fps; // Start moments sometimes give useless 1
if (max < fps) max = fps; if (max < fps) max = fps;
if (low > kilotris) low = kilotris; if (low > kilotris) low = kilotris;
@ -1863,17 +1863,15 @@ void IrrDriver::RTTProvider::setupRTTScene(PtrVector<scene::IMesh, REF>& mesh,
} }
} }
irr_driver->getSceneManager()->setAmbientLight(video::SColor(255, 120, irr_driver->getSceneManager()->setAmbientLight(video::SColor(255, 10, 10, 10) );
120, 120) );
const core::vector3df &sun_pos = core::vector3df( 0, 200, 100.0f ); const core::vector3df &spot_pos = core::vector3df(30, 30, 30);
m_light = irr_driver->getSceneManager() m_light = irr_driver->getSceneManager()
->addLightSceneNode(NULL, sun_pos, video::SColorf(1.0f,1.0f,1.0f), ->addLightSceneNode(NULL, spot_pos, video::SColorf(1.0f,1.0f,1.0f),
10000.0f /* radius */); 1600 /* radius */);
m_light->getLightData().DiffuseColor m_light->setLightType(video::ELT_SPOT);
= video::SColorf(0.5f, 0.5f, 0.5f, 0.5f); m_light->setRotation((core::vector3df(0, 10, 0) - spot_pos).getHorizontalAngle());
m_light->getLightData().SpecularColor m_light->updateAbsolutePosition();
= video::SColorf(1.0f, 1.0f, 1.0f, 1.0f);
m_rtt_main_node->setMaterialFlag(video::EMF_GOURAUD_SHADING , true); m_rtt_main_node->setMaterialFlag(video::EMF_GOURAUD_SHADING , true);
m_rtt_main_node->setMaterialFlag(video::EMF_LIGHTING, true); m_rtt_main_node->setMaterialFlag(video::EMF_LIGHTING, true);

View File

@ -483,6 +483,7 @@ Material::Material(const XMLNode *node, int index, bool deprecated)
node->get("mask", &m_mask ); node->get("mask", &m_mask );
node->get("water-splash", &m_water_splash ); node->get("water-splash", &m_water_splash );
node->get("jump", &m_is_jump_texture );
if (m_collision_reaction != NORMAL) if (m_collision_reaction != NORMAL)
{ {
@ -732,6 +733,7 @@ void Material::init(unsigned int index)
m_is_heightmap = false; m_is_heightmap = false;
m_alpha_to_coverage = false; m_alpha_to_coverage = false;
m_water_splash = false; m_water_splash = false;
m_is_jump_texture = false;
m_shaders.resize(SHADER_COUNT, NULL); m_shaders.resize(SHADER_COUNT, NULL);

View File

@ -114,11 +114,16 @@ private:
* surface is not a physical object), but the location of the water * surface is not a physical object), but the location of the water
* effect is on the surface. */ * effect is on the surface. */
bool m_surface; bool m_surface;
/** If the material is a zipper, i.e. gives a speed boost. */ /** If the material is a zipper, i.e. gives a speed boost. */
bool m_zipper; bool m_zipper;
/** If a kart is rescued when driving on this surface. */ /** If a kart is rescued when driving on this surface. */
bool m_drive_reset; bool m_drive_reset;
/** True if this is a texture that will start the jump animatoin when
* leaving it and being in the air. */
bool m_is_jump_texture;
/** Speed of the 'main' wave in the water shader. Only used if /** Speed of the 'main' wave in the water shader. Only used if
m_graphical_effect == WATER_SHADER */ m_graphical_effect == WATER_SHADER */
@ -321,6 +326,10 @@ public:
* the special falling camera. */ * the special falling camera. */
bool hasFallingEffect() const {return m_falling_effect; } bool hasFallingEffect() const {return m_falling_effect; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns if being in the air after this texture should start the
* jump animation. */
bool isJumpTexture() const { return m_is_jump_texture; }
// ------------------------------------------------------------------------
/** Returns the zipper parametersfor the current material. */ /** Returns the zipper parametersfor the current material. */
void getZipperParameter(float *zipper_max_speed_increase, void getZipperParameter(float *zipper_max_speed_increase,
float *zipper_duration, float *zipper_duration,

View File

@ -187,9 +187,8 @@ void ModalDialog::dismiss()
{ {
if(modalWindow != NULL) delete modalWindow; if(modalWindow != NULL) delete modalWindow;
modalWindow = NULL; modalWindow = NULL;
GUIEngine::Screen* scr = GUIEngine::getCurrentScreen(); if(GUIEngine::getCurrentScreen() != NULL)
if (scr) GUIEngine::getCurrentScreen()->onDialogClose();
scr->onDialogClose();
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -115,7 +115,7 @@ void CGUISTKListBox::removeItem(u32 id)
else if ((u32)Selected > id) else if ((u32)Selected > id)
{ {
Selected -= 1; Selected -= 1;
selectTime = Time::getTimeSinceEpoch(); selectTime = (u32)Time::getTimeSinceEpoch();
} }
Items.erase(id); Items.erase(id);
@ -205,7 +205,7 @@ void CGUISTKListBox::setSelected(s32 id)
else else
Selected = id; Selected = id;
selectTime = Time::getTimeSinceEpoch(); selectTime = (u32)Time::getTimeSinceEpoch();
recalculateScrollPos(); recalculateScrollPos();
} }
@ -397,7 +397,7 @@ bool CGUISTKListBox::OnEvent(const SEvent& event)
void CGUISTKListBox::selectNew(s32 ypos, bool onlyHover) void CGUISTKListBox::selectNew(s32 ypos, bool onlyHover)
{ {
u32 now = Time::getTimeSinceEpoch(); u32 now = (u32)Time::getTimeSinceEpoch();
s32 oldSelected = Selected; s32 oldSelected = Selected;
Selected = getItemAt(AbsoluteRect.UpperLeftCorner.X, ypos); Selected = getItemAt(AbsoluteRect.UpperLeftCorner.X, ypos);
@ -486,13 +486,13 @@ void CGUISTKListBox::draw()
if (Font) if (Font)
{ {
int total_proportion = 0; int total_proportion = 0;
for(int x = 0; x < Items[i].m_contents.size(); ++x) for(unsigned int x = 0; x < Items[i].m_contents.size(); ++x)
{ {
total_proportion += Items[i].m_contents[x].m_proportion; total_proportion += Items[i].m_contents[x].m_proportion;
} }
int part_size = (int)(textRect.getWidth() / float(total_proportion)); int part_size = (int)(textRect.getWidth() / float(total_proportion));
for(int x = 0; x < Items[i].m_contents.size(); ++x) for(unsigned int x = 0; x < Items[i].m_contents.size(); ++x)
{ {
textRect.LowerRightCorner.X = textRect.UpperLeftCorner.X + textRect.LowerRightCorner.X = textRect.UpperLeftCorner.X +
(Items[i].m_contents[x].m_proportion * part_size); (Items[i].m_contents[x].m_proportion * part_size);
@ -511,7 +511,7 @@ void CGUISTKListBox::draw()
iconPos, &clientClip, iconPos, &clientClip,
hasItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) ? hasItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) ?
getItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_ICON_HIGHLIGHT), getItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_ICON_HIGHLIGHT),
selectTime, Time::getTimeSinceEpoch(), false, true); selectTime, (u32)Time::getTimeSinceEpoch(), false, true);
} }
else else
{ {
@ -520,7 +520,7 @@ void CGUISTKListBox::draw()
iconPos, iconPos,
&clientClip, &clientClip,
hasItemOverrideColor(i, EGUI_LBC_ICON) ? getItemOverrideColor(i, EGUI_LBC_ICON) : getItemDefaultColor(EGUI_LBC_ICON), hasItemOverrideColor(i, EGUI_LBC_ICON) ? getItemOverrideColor(i, EGUI_LBC_ICON) : getItemDefaultColor(EGUI_LBC_ICON),
0 , (i==Selected) ? Time::getTimeSinceEpoch() : 0, false, true); 0 , (i==Selected) ? (u32)Time::getTimeSinceEpoch() : 0, false, true);
} }
textRect.UpperLeftCorner.X += ItemsIconWidth; textRect.UpperLeftCorner.X += ItemsIconWidth;
} }

View File

@ -128,12 +128,11 @@ void LabelWidget::add()
void LabelWidget::setText(const wchar_t *text, bool expandIfNeeded) void LabelWidget::setText(const wchar_t *text, bool expandIfNeeded)
{ {
assert(m_element != NULL);
m_scroll_offset = 0; m_scroll_offset = 0;
if (expandIfNeeded) if (expandIfNeeded)
{ {
assert(m_element != NULL);
const int fwidth = (m_title_font ? GUIEngine::getTitleFont() : GUIEngine::getFont())->getDimension(text).Width; const int fwidth = (m_title_font ? GUIEngine::getTitleFont() : GUIEngine::getFont())->getDimension(text).Width;
core::rect<s32> rect = m_element->getRelativePosition(); core::rect<s32> rect = m_element->getRelativePosition();

View File

@ -531,6 +531,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
else if (button == KEY_RIGHT) action = PA_MENU_RIGHT; else if (button == KEY_RIGHT) action = PA_MENU_RIGHT;
else if (button == KEY_SPACE) action = PA_MENU_SELECT; else if (button == KEY_SPACE) action = PA_MENU_SELECT;
else if (button == KEY_RETURN) action = PA_MENU_SELECT; else if (button == KEY_RETURN) action = PA_MENU_SELECT;
else if (button == KEY_TAB) action = PA_MENU_DOWN;
if (button == KEY_RETURN && GUIEngine::ModalDialog::isADialogActive()) if (button == KEY_RETURN && GUIEngine::ModalDialog::isADialogActive())
{ {

View File

@ -854,10 +854,8 @@ void FileManager::redirectOutput()
{ {
//Enable logging of stdout and stderr to logfile //Enable logging of stdout and stderr to logfile
std::string logoutfile = getLogFile("stdout.log"); std::string logoutfile = getLogFile("stdout.log");
std::string logerrfile = getLogFile("stderr.log");
Log::verbose("main", "Error messages and other text output will " Log::verbose("main", "Error messages and other text output will "
"be logged to %s and %s.", logoutfile.c_str(), "be logged to %s.", logoutfile.c_str());
logerrfile.c_str());
Log::openOutputFiles(logoutfile); Log::openOutputFiles(logoutfile);
} // redirectOutput } // redirectOutput

View File

@ -317,6 +317,11 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual void setEnergy(float val) = 0; virtual void setEnergy(float val) = 0;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Return whether nitro is being used despite the nitro button not being
* pressed due to minimal use time requirements
*/
virtual float isOnMinNitroTime() const = 0;
// ------------------------------------------------------------------------
/** Returns the current material the kart is on. */ /** Returns the current material the kart is on. */
virtual const Material *getMaterial() const = 0; virtual const Material *getMaterial() const = 0;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -117,10 +117,10 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
m_flying = false; m_flying = false;
m_sky_particles_emitter= NULL; m_sky_particles_emitter= NULL;
m_stars_effect = NULL; m_stars_effect = NULL;
m_timeFlying = 0; m_jump_time = 0;
m_isTimeFlying = false; m_is_jumping = false;
m_hitGround = NULL; m_min_nitro_time = 0.0f;
m_view_blocked_by_plunger = 0; m_view_blocked_by_plunger = 0;
m_has_caught_nolok_bubblegum = false; m_has_caught_nolok_bubblegum = false;
@ -293,6 +293,8 @@ void Kart::reset()
if(m_body) if(m_body)
World::getWorld()->getPhysics()->addKart(this); World::getWorld()->getPhysics()->addKart(this);
m_min_nitro_time = 0.0f;
// Reset star effect in case that it is currently being shown. // Reset star effect in case that it is currently being shown.
m_stars_effect->reset(); m_stars_effect->reset();
m_max_speed->reset(); m_max_speed->reset();
@ -337,6 +339,8 @@ void Kart::reset()
m_bubblegum_time = 0.0f; m_bubblegum_time = 0.0f;
m_bubblegum_torque = 0.0f; m_bubblegum_torque = 0.0f;
m_has_caught_nolok_bubblegum = false; m_has_caught_nolok_bubblegum = false;
m_is_jumping = false;
// In case that the kart was in the air, in which case its // In case that the kart was in the air, in which case its
// linear damping is 0 // linear damping is 0
m_body->setDamping(m_kart_properties->getChassisLinearDamping(), m_body->setDamping(m_kart_properties->getChassisLinearDamping(),
@ -1179,17 +1183,39 @@ void Kart::update(float dt)
// values for the raycasts). // values for the raycasts).
if (!isOnGround()) if (!isOnGround())
{ {
m_timeFlying+=dt; const Material *m = getMaterial();
m_isTimeFlying = true; const Material *last_m = getLastMaterial();
// A jump starts only the kart isn't already jumping, is on a new
// (or no) texture.
if(!m_is_jumping && last_m && last_m!=m )
{
float v = getVelocity().getY();
float force = World::getWorld()->getTrack()->getGravity();;
// Velocity / force is the time it takes to reach the peak
// of the jump (i.e. when vertical speed becomes 0). Assuming
// that jump start height and end height are the same, it will
// take the same time again to reach the bottom
float t = 2.0f * v/force;
// Jump if either the jump is estimated to be long enough, or
// the texture has the jump property set.
if(t>getKartProperties()->getJumpAnimationTime() ||
last_m->isJumpTexture() )
m_kart_model->setAnimation(KartModel::AF_JUMP_START);
m_is_jumping = true;
}
m_jump_time+=dt;
} }
else if (m_is_jumping)
if(isOnGround() && m_isTimeFlying)
{ {
m_isTimeFlying = false; // Kart touched ground again
m_hitGround = new Explosion(getXYZ(), "jump", m_is_jumping = false;
"jump_explosion.xml"); HitEffect *effect = new Explosion(getXYZ(), "jump",
projectile_manager->addHitEffect(m_hitGround); "jump_explosion.xml");
m_timeFlying = 0; projectile_manager->addHitEffect(effect);
m_kart_model->setAnimation(KartModel::AF_DEFAULT);
m_jump_time = 0;
} }
if( (!isOnGround() || emergency) && m_shadow_enabled) if( (!isOnGround() || emergency) && m_shadow_enabled)
@ -1489,18 +1515,40 @@ void Kart::handleZipper(const Material *material, bool play_sound)
*/ */
void Kart::updateNitro(float dt) void Kart::updateNitro(float dt)
{ {
if(!m_controls.m_nitro || !isOnGround()) return; if (m_controls.m_nitro && m_min_nitro_time <= 0.0f)
{
m_min_nitro_time = m_kart_properties->getNitroMinConsumptionTime();
}
if (m_min_nitro_time > 0.0f)
{
m_min_nitro_time -= dt;
// when pressing the key, don't allow the min time to go under zero.
// If it went under zero, it would be reset
if (m_controls.m_nitro && m_min_nitro_time <= 0.0f)
m_min_nitro_time = 0.1f;
}
bool increase_speed = (m_controls.m_nitro && isOnGround());
if (!increase_speed && m_min_nitro_time <= 0.0f)
{
return;
}
m_collected_energy -= dt * m_kart_properties->getNitroConsumption(); m_collected_energy -= dt * m_kart_properties->getNitroConsumption();
if(m_collected_energy<0) if (m_collected_energy < 0)
{ {
m_collected_energy = 0; m_collected_energy = 0;
return; return;
} }
m_max_speed->increaseMaxSpeed(MaxSpeed::MS_INCREASE_NITRO,
m_kart_properties->getNitroMaxSpeedIncrease(), if (increase_speed)
m_kart_properties->getNitroEngineForce(), {
m_kart_properties->getNitroDuration(), m_max_speed->increaseMaxSpeed(MaxSpeed::MS_INCREASE_NITRO,
m_kart_properties->getNitroFadeOutTime() ); m_kart_properties->getNitroMaxSpeedIncrease(),
m_kart_properties->getNitroEngineForce(),
m_kart_properties->getNitroDuration(),
m_kart_properties->getNitroFadeOutTime() );
}
} // updateNitro } // updateNitro
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -2233,7 +2281,7 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
y += m_skidding->getGraphicalJumpOffset(); y += m_skidding->getGraphicalJumpOffset();
center_shift.setY(y); center_shift.setY(y);
if (m_controls.m_nitro && isOnGround() && m_collected_energy > 0) if ((m_controls.m_nitro || m_min_nitro_time > 0.0f) && isOnGround() && m_collected_energy > 0)
{ {
// fabs(speed) is important, otherwise the negative number will // fabs(speed) is important, otherwise the negative number will
// become a huge unsigned number in the particle scene node! // become a huge unsigned number in the particle scene node!

View File

@ -41,6 +41,7 @@ class Attachment;
class Controller; class Controller;
class Item; class Item;
class AbstractKartAnimation; class AbstractKartAnimation;
class HitEffect;
class KartGFX; class KartGFX;
class MaxSpeed; class MaxSpeed;
class ParticleEmitter; class ParticleEmitter;
@ -51,7 +52,6 @@ class Skidding;
class SkidMarks; class SkidMarks;
class SlipStream; class SlipStream;
class Stars; class Stars;
class HitEffect;
/** The main kart class. All type of karts are of this object, but with /** The main kart class. All type of karts are of this object, but with
* different controllers. The controllers are what turn a kart into a * different controllers. The controllers are what turn a kart into a
@ -149,14 +149,11 @@ private:
// Graphical effects // Graphical effects
// ----------------- // -----------------
/** The time where a kart is flying */ /** Time a kart is jumping. */
float m_timeFlying; float m_jump_time;
/** For the effect when the kart touch the ground */
HitEffect *m_hitGround;
/** Is time flying activated */ /** Is time flying activated */
bool m_isTimeFlying; bool m_is_jumping;
/** The shadow of a kart. */ /** The shadow of a kart. */
Shadow *m_shadow; Shadow *m_shadow;
@ -210,6 +207,9 @@ private:
SFXBase *m_skid_sound; SFXBase *m_skid_sound;
SFXBase *m_goo_sound; SFXBase *m_goo_sound;
float m_time_last_crash; float m_time_last_crash;
/** To prevent using nitro in too short bursts */
float m_min_nitro_time;
void updatePhysics(float dt); void updatePhysics(float dt);
void handleMaterialSFX(const Material *material); void handleMaterialSFX(const Material *material);
@ -403,6 +403,11 @@ public:
/** Sets the energy the kart has collected. */ /** Sets the energy the kart has collected. */
virtual void setEnergy(float val) { m_collected_energy = val; } virtual void setEnergy(float val) { m_collected_energy = val; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Return whether nitro is being used despite the nitro button not being
* pressed due to minimal use time requirements
*/
virtual float isOnMinNitroTime() const { return m_min_nitro_time > 0.0f; }
// ------------------------------------------------------------------------
/** Returns if the kart is currently being squashed. */ /** Returns if the kart is currently being squashed. */
virtual bool isSquashed() const { return m_squash_time >0; } virtual bool isSquashed() const { return m_squash_time >0; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -120,6 +120,9 @@ void KartModel::loadInfo(const XMLNode &node)
animation_node->get("end-losing", &m_animation_frame[AF_LOSE_END] ); animation_node->get("end-losing", &m_animation_frame[AF_LOSE_END] );
animation_node->get("start-explosion",&m_animation_frame[AF_LOSE_START]); animation_node->get("start-explosion",&m_animation_frame[AF_LOSE_START]);
animation_node->get("end-explosion", &m_animation_frame[AF_LOSE_END] ); animation_node->get("end-explosion", &m_animation_frame[AF_LOSE_END] );
animation_node->get("start-jump", &m_animation_frame[AF_JUMP_START]);
animation_node->get("start-jump-loop",&m_animation_frame[AF_JUMP_LOOP] );
animation_node->get("end-jump", &m_animation_frame[AF_JUMP_END] );
animation_node->get("speed", &m_animation_speed ); animation_node->get("speed", &m_animation_speed );
} }
@ -130,14 +133,6 @@ void KartModel::loadInfo(const XMLNode &node)
loadWheelInfo(*wheels_node, "rear-right", 2); loadWheelInfo(*wheels_node, "rear-right", 2);
loadWheelInfo(*wheels_node, "rear-left", 3); loadWheelInfo(*wheels_node, "rear-left", 3);
} }
// FIXME fallback for karts that don't have nitro emitter
/*
m_nitro_emitter_position[0] = Vec3 (0, m_kart_height*0.35f,
-m_kart_length*0.35f);
m_nitro_emitter_position[1] = Vec3 (0, m_kart_height*0.35f,
-m_kart_length*0.35f); */
m_nitro_emitter_position[0] = Vec3 (0,0.1f,0); m_nitro_emitter_position[0] = Vec3 (0,0.1f,0);
@ -569,6 +564,8 @@ void KartModel::setAnimation(AnimationFrameType type)
// 'type' is the start frame of the animation, type + 1 the frame // 'type' is the start frame of the animation, type + 1 the frame
// to begin the loop with, type + 2 to end the frame with // to begin the loop with, type + 2 to end the frame with
AnimationFrameType end = (AnimationFrameType)(type+2); AnimationFrameType end = (AnimationFrameType)(type+2);
if(m_animation_frame[end]==-1)
end = (AnimationFrameType)((int)end-1);
m_animated_node->setAnimationSpeed(m_animation_speed); m_animated_node->setAnimationSpeed(m_animation_speed);
m_animated_node->setFrameLoop(m_animation_frame[type], m_animated_node->setFrameLoop(m_animation_frame[type],
m_animation_frame[end] ); m_animation_frame[end] );
@ -613,10 +610,16 @@ void KartModel::OnAnimationEnd(scene::IAnimatedMeshSceneNode *node)
if(m_animation_frame[start]==-1) if(m_animation_frame[start]==-1)
start = m_current_animation; start = m_current_animation;
AnimationFrameType end = (AnimationFrameType)(m_current_animation+2); AnimationFrameType end = (AnimationFrameType)(m_current_animation+2);
m_animated_node->setAnimationSpeed(m_animation_speed);
m_animated_node->setFrameLoop(m_animation_frame[start], // Switch to loop mode if the current animation has a loop defined
m_animation_frame[end] ); // (else just disable the callback, and the last frame will be shown).
m_animated_node->setLoopMode(true); if(m_animation_frame[end]>-1)
{
m_animated_node->setAnimationSpeed(m_animation_speed);
m_animated_node->setFrameLoop(m_animation_frame[start],
m_animation_frame[end] );
m_animated_node->setLoopMode(true);
}
m_animated_node->setAnimationEndCallback(NULL); m_animated_node->setAnimationEndCallback(NULL);
} // OnAnimationEnd } // OnAnimationEnd

View File

@ -60,6 +60,9 @@ public:
AF_LOSE_END, // End losing animation AF_LOSE_END, // End losing animation
AF_BEGIN_EXPLOSION, // Begin explosion animation AF_BEGIN_EXPLOSION, // Begin explosion animation
AF_END_EXPLOSION, // End explosion animation AF_END_EXPLOSION, // End explosion animation
AF_JUMP_START, // Begin of jump
AF_JUMP_LOOP, // Begin of jump loop
AF_JUMP_END, // End of jump
AF_WIN_START, // Begin of win animation AF_WIN_START, // Begin of win animation
AF_WIN_LOOP_START, // Begin of win loop animation AF_WIN_LOOP_START, // Begin of win loop animation
AF_WIN_END, // End of win animation AF_WIN_END, // End of win animation

View File

@ -90,7 +90,8 @@ KartProperties::KartProperties(const std::string &filename)
m_swatter_distance2 = m_swatter_duration = m_squash_slowdown = m_swatter_distance2 = m_swatter_duration = m_squash_slowdown =
m_squash_duration = m_downward_impulse_factor = m_squash_duration = m_downward_impulse_factor =
m_bubblegum_fade_in_time = m_bubblegum_speed_fraction = m_bubblegum_fade_in_time = m_bubblegum_speed_fraction =
m_bubblegum_time = m_bubblegum_torque = UNDEFINED; m_bubblegum_time = m_bubblegum_torque = m_jump_animation_time =
UNDEFINED;
m_engine_power.resize(RaceManager::DIFFICULTY_COUNT, UNDEFINED); m_engine_power.resize(RaceManager::DIFFICULTY_COUNT, UNDEFINED);
m_max_speed.resize(RaceManager::DIFFICULTY_COUNT, UNDEFINED); m_max_speed.resize(RaceManager::DIFFICULTY_COUNT, UNDEFINED);
@ -107,6 +108,7 @@ KartProperties::KartProperties(const std::string &filename)
m_engine_sfx_type = "engine_small"; m_engine_sfx_type = "engine_small";
m_kart_model = NULL; m_kart_model = NULL;
m_has_rand_wheels = false; m_has_rand_wheels = false;
m_nitro_min_consumption = 1.0f;
// The default constructor for stk_config uses filename="" // The default constructor for stk_config uses filename=""
if (filename != "") if (filename != "")
{ {
@ -312,6 +314,7 @@ void KartProperties::getAllData(const XMLNode * root)
nitro_node->get("duration", &m_nitro_duration ); nitro_node->get("duration", &m_nitro_duration );
nitro_node->get("fade-out-time", &m_nitro_fade_out_time ); nitro_node->get("fade-out-time", &m_nitro_fade_out_time );
nitro_node->get("max", &m_nitro_max ); nitro_node->get("max", &m_nitro_max );
nitro_node->get("min-consumption-time", &m_nitro_min_consumption );
} }
if(const XMLNode *bubble_node = root->getNode("bubblegum")) if(const XMLNode *bubble_node = root->getNode("bubblegum"))
@ -519,6 +522,11 @@ void KartProperties::getAllData(const XMLNode * root)
m_lean_speed *= DEGREE_TO_RAD; m_lean_speed *= DEGREE_TO_RAD;
} }
if(const XMLNode *jump_node= root->getNode("jump"))
{
jump_node->get("animation-time", &m_jump_animation_time);
}
if(const XMLNode *camera_node= root->getNode("camera")) if(const XMLNode *camera_node= root->getNode("camera"))
{ {
camera_node->get("distance", &m_camera_distance); camera_node->get("distance", &m_camera_distance);

View File

@ -176,6 +176,11 @@ private:
/** Vertical offset after rescue. */ /** Vertical offset after rescue. */
float m_rescue_vert_offset; float m_rescue_vert_offset;
/** Minimum time during which nitro is consumed when pressing
* the nitro key (to prevent using in very small bursts)
*/
float m_nitro_min_consumption;
/** Filename of the wheel models. */ /** Filename of the wheel models. */
std::string m_wheel_filename[4]; std::string m_wheel_filename[4];
/** Radius of the graphical wheels. */ /** Radius of the graphical wheels. */
@ -243,6 +248,9 @@ private:
* (in radians/second). */ * (in radians/second). */
float m_lean_speed; float m_lean_speed;
/** How long a jump must be in order to trigger the jump animation. */
float m_jump_animation_time;
/** Engine sound effect. */ /** Engine sound effect. */
std::string m_engine_sfx_type; std::string m_engine_sfx_type;
@ -844,9 +852,17 @@ public:
/** The speed with which a kart should lean (in radians/s). */ /** The speed with which a kart should lean (in radians/s). */
float getLeanSpeed() const { return m_lean_speed; } float getLeanSpeed() const { return m_lean_speed; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Return show long a jump must last in order to play the jump
* animation. */
float getJumpAnimationTime() const { return m_jump_animation_time; }
// ------------------------------------------------------------------------
/** Returns true if wheels should have random rotation at start. */ /** Returns true if wheels should have random rotation at start. */
bool hasRandomWheels() const { return m_has_rand_wheels; } bool hasRandomWheels() const { return m_has_rand_wheels; }
// ------------------------------------------------------------------------
/** Returns minimum time during which nitro is consumed when pressing nitro
* key, to prevent using nitro in very short bursts
*/
float getNitroMinConsumptionTime() const { return m_nitro_min_consumption; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the bevel factor (!=0 indicates to use a bevelled box). */ /** Returns the bevel factor (!=0 indicates to use a bevelled box). */
const Vec3 &getBevelFactor() const { return m_bevel_factor; } const Vec3 &getBevelFactor() const { return m_bevel_factor; }

View File

@ -1110,8 +1110,7 @@ int handleCmdLine(int argc, char **argv)
{ {
irr::core::stringw s; irr::core::stringw s;
Online::CurrentUser::SignInRequest* request = Online::CurrentUser::SignInRequest* request =
Online::CurrentUser::acquire()->requestSignIn(login, password, false, false); Online::CurrentUser::get()->requestSignIn(login, password, false, false);
Online::CurrentUser::release();
Online::HTTPManager::get()->synchronousRequest(request); Online::HTTPManager::get()->synchronousRequest(request);
if (request->isSuccess()) if (request->isSuccess())

View File

@ -162,6 +162,7 @@ void MainLoop::run()
PROFILER_POP_CPU_MARKER(); PROFILER_POP_CPU_MARKER();
} }
PROFILER_SYNC_FRAME();
PROFILER_POP_CPU_MARKER(); PROFILER_POP_CPU_MARKER();
} // while !m_exit } // while !m_exit

View File

@ -416,37 +416,11 @@ bool CutsceneWorld::isRaceOver()
return m_time > m_duration; return m_time > m_duration;
} // isRaceOver } // isRaceOver
//-----------------------------------------------------------------------------
/** Called when the race finishes, i.e. after playing (if necessary) an
* end of race animation. It updates the time for all karts still racing,
* and then updates the ranks.
*/
void CutsceneWorld::terminateRace()
{
World::terminateRace();
} // terminateRace
//-----------------------------------------------------------------------------
/** Returns the data to display in the race gui.
*/
void CutsceneWorld::getKartsDisplayInfo(
std::vector<RaceGUIBase::KartIconDisplayInfo> *info)
{
} // getKartDisplayInfo
//-----------------------------------------------------------------------------
/** Moves a kart to its rescue position.
* \param kart The kart that was rescued.
*/
void CutsceneWorld::moveKartAfterRescue(AbstractKart* kart)
{
} // moveKartAfterRescue
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CutsceneWorld::createRaceGUI() void CutsceneWorld::createRaceGUI()
{ {
m_race_gui = new CutsceneGUI(); m_race_gui = new CutsceneGUI();
} } // createRaceGUI

View File

@ -68,17 +68,6 @@ public:
// clock events // clock events
virtual bool isRaceOver() OVERRIDE; virtual bool isRaceOver() OVERRIDE;
virtual void terminateRace() OVERRIDE;
void setParts(std::vector<std::string> parts)
{
m_parts = parts;
}
virtual void getKartsDisplayInfo(
std::vector<RaceGUIBase::KartIconDisplayInfo> *info) OVERRIDE;
virtual bool raceHasLaps() OVERRIDE { return false; }
virtual void moveKartAfterRescue(AbstractKart* kart) OVERRIDE;
virtual const std::string& getIdent() const OVERRIDE; virtual const std::string& getIdent() const OVERRIDE;
@ -88,8 +77,35 @@ public:
virtual void enterRaceOverState() OVERRIDE; virtual void enterRaceOverState() OVERRIDE;
// ------------------------------------------------------------------------
virtual bool raceHasLaps() OVERRIDE { return false; }
// ------------------------------------------------------------------------
virtual unsigned int getNumberOfRescuePositions() const OVERRIDE
{
return 0;
} // getNumberOfRescuePositions
// ------------------------------------------------------------------------
virtual unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE
{
return 0;
} // getRescuePositionIndex
// ------------------------------------------------------------------------
virtual btTransform getRescueTransform(unsigned int index) const OVERRIDE
{
return btTransform();
} // getRescueTransform
// ------------------------------------------------------------------------
virtual void onFirePressed(Controller* who) OVERRIDE { abortCutscene(); } virtual void onFirePressed(Controller* who) OVERRIDE { abortCutscene(); }
// ------------------------------------------------------------------------
void setParts(std::vector<std::string> parts) { m_parts = parts; }
// ------------------------------------------------------------------------
/** Returns the data to display in the race gui.
*/
virtual void getKartsDisplayInfo(
std::vector<RaceGUIBase::KartIconDisplayInfo> *info) OVERRIDE
{
};
// ------------------------------------------------------------------------
virtual void escapePressed() OVERRIDE { abortCutscene(); } virtual void escapePressed() OVERRIDE { abortCutscene(); }
}; // CutsceneWorld }; // CutsceneWorld

View File

@ -206,15 +206,3 @@ void EasterEggHunt::getKartsDisplayInfo(
} }
} // getKartDisplayInfo } // getKartDisplayInfo
//-----------------------------------------------------------------------------
/** Moves a kart to its rescue position.
* \param kart The kart that was rescued.
*/
void EasterEggHunt::moveKartAfterRescue(AbstractKart* kart)
{
int start_position = kart->getInitialPosition();
btTransform start_pos = getTrack()->getStartTransform(start_position-1);
kart->getBody()->setCenterOfMassTransform(start_pos);
} // moveKartAfterRescue

View File

@ -54,7 +54,6 @@ public:
virtual void reset(); virtual void reset();
virtual bool raceHasLaps(){ return false; } virtual bool raceHasLaps(){ return false; }
virtual void moveKartAfterRescue(AbstractKart* kart);
virtual const std::string& getIdent() const; virtual const std::string& getIdent() const;

View File

@ -88,7 +88,7 @@ void LinearWorld::reset()
for(unsigned int i=0; i<kart_amount; i++) for(unsigned int i=0; i<kart_amount; i++)
{ {
m_kart_info[i].reset(); m_kart_info[i].reset();
m_kart_info[i].getSector()->update(m_karts[i]->getXYZ()); m_kart_info[i].getTrackSector()->update(m_karts[i]->getXYZ());
} // next kart } // next kart
// At the moment the last kart would be the one that is furthest away // At the moment the last kart would be the one that is furthest away
@ -171,7 +171,7 @@ void LinearWorld::update(float dt)
// rescued or eliminated // rescued or eliminated
if(kart->getKartAnimation()) continue; if(kart->getKartAnimation()) continue;
kart_info.getSector()->update(kart->getXYZ()); kart_info.getTrackSector()->update(kart->getXYZ());
kart_info.m_overall_distance = kart_info.m_race_lap kart_info.m_overall_distance = kart_info.m_race_lap
* m_track->getTrackLength() * m_track->getTrackLength()
+ getDistanceDownTrackForKart(kart->getWorldKartId()); + getDistanceDownTrackForKart(kart->getWorldKartId());
@ -369,7 +369,7 @@ int LinearWorld::getSectorForKart(const AbstractKart *kart) const
{ {
if(kart->getWorldKartId()>=m_kart_info.size()) if(kart->getWorldKartId()>=m_kart_info.size())
return QuadGraph::UNKNOWN_SECTOR; return QuadGraph::UNKNOWN_SECTOR;
return m_kart_info[kart->getWorldKartId()].getSector() return m_kart_info[kart->getWorldKartId()].getTrackSector()
->getCurrentGraphNode(); ->getCurrentGraphNode();
} // getSectorForKart } // getSectorForKart
@ -381,7 +381,7 @@ int LinearWorld::getSectorForKart(const AbstractKart *kart) const
float LinearWorld::getDistanceDownTrackForKart(const int kart_id) const float LinearWorld::getDistanceDownTrackForKart(const int kart_id) const
{ {
assert(kart_id < (int)m_kart_info.size()); assert(kart_id < (int)m_kart_info.size());
return m_kart_info[kart_id].getSector()->getDistanceFromStart(); return m_kart_info[kart_id].getTrackSector()->getDistanceFromStart();
} // getDistanceDownTrackForKart } // getDistanceDownTrackForKart
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -392,7 +392,7 @@ float LinearWorld::getDistanceDownTrackForKart(const int kart_id) const
float LinearWorld::getDistanceToCenterForKart(const int kart_id) const float LinearWorld::getDistanceToCenterForKart(const int kart_id) const
{ {
assert(kart_id < (int)m_kart_info.size()); assert(kart_id < (int)m_kart_info.size());
return m_kart_info[kart_id].getSector()->getDistanceToCenter(); return m_kart_info[kart_id].getTrackSector()->getDistanceToCenter();
} // getDistanceToCenterForKart } // getDistanceToCenterForKart
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -598,58 +598,37 @@ float LinearWorld::estimateFinishTimeForKart(AbstractKart* kart)
return est_time; return est_time;
} // estimateFinishTimeForKart } // estimateFinishTimeForKart
//----------------------------------------------------------------------------- // ------------------------------------------------------------------------
/** Decide where to drop a rescued kart /** Returns the number of rescue positions on a given track, which in
* linear races is just the number of driveline quads.
*/ */
void LinearWorld::moveKartAfterRescue(AbstractKart* kart) unsigned int LinearWorld::getNumberOfRescuePositions() const
{
return QuadGraph::get()->getNumNodes();
} // getNumberOfRescuePositions
// ------------------------------------------------------------------------
unsigned int LinearWorld::getRescuePositionIndex(AbstractKart *kart)
{ {
KartInfo& info = m_kart_info[kart->getWorldKartId()]; KartInfo& info = m_kart_info[kart->getWorldKartId()];
info.getSector()->rescue(); info.getTrackSector()->rescue();
// Setting XYZ for the kart is important since otherwise the kart // Setting XYZ for the kart is important since otherwise the kart
// will not detect the right material again when doing the next // will not detect the right material again when doing the next
// raycast to detect where it is driving on (--> potential rescue loop) // raycast to detect where it is driving on (--> potential rescue loop)
int sector = info.getSector()->getCurrentGraphNode(); return info.getTrackSector()->getCurrentGraphNode();
kart->setXYZ( QuadGraph::get()->getQuadOfNode(sector).getCenter()); } // getRescuePositionIndex
btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f), // ------------------------------------------------------------------------
m_track->getAngle(sector) ); btTransform LinearWorld::getRescueTransform(unsigned int index) const
kart->setRotation(heading); {
// A certain epsilon is added here to the Z coordinate, in case const Vec3 &xyz = QuadGraph::get()->getQuadOfNode(index).getCenter();
// that the drivelines are somewhat under the track. Otherwise, the
// kart might be placed a little bit under the track, triggering
// a rescue, ... (experimentally found value)
float epsilon = 0.5f * kart->getKartHeight();
const Vec3 &xyz = QuadGraph::get()->getQuadOfNode(sector).getCenter();
btTransform pos; btTransform pos;
pos.setOrigin(xyz+btVector3(0, kart->getKartHeight() + epsilon,0)); pos.setOrigin(xyz);
pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f), pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f),
m_track->getAngle(sector))); m_track->getAngle(index)));
return pos;
kart->getBody()->setCenterOfMassTransform(pos); } // getRescueTransform
kart->setXYZ(pos.getOrigin());
//project kart to surface of track
bool kart_over_ground = m_track->findGround(kart);
if (kart_over_ground)
{
//add vertical offset so that the kart starts off above the track
float vertical_offset =
kart->getKartProperties()->getVertRescueOffset()
* kart->getKartHeight();
kart->getBody()->translate(btVector3(0, vertical_offset, 0));
// Also correctly set the graphics, otherwise the kart will
// be displayed for one frame at the incorrect position.
kart->updateGraphics(0, Vec3(0,0,0), btQuaternion(0, 0, 0, 1));
}
else
{
fprintf(stderr, "WARNING: invalid position after rescue for kart %s "
"on track %s.\n",
(kart->getIdent().c_str()), m_track->getIdent().c_str());
}
} // moveKartAfterRescue
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Find the position (rank) of every kart. ATM it uses a stable O(n^2) /** Find the position (rank) of every kart. ATM it uses a stable O(n^2)
@ -842,14 +821,14 @@ void LinearWorld::updateRacePosition()
void LinearWorld::checkForWrongDirection(unsigned int i) void LinearWorld::checkForWrongDirection(unsigned int i)
{ {
if(!m_karts[i]->getController()->isPlayerController()) return; if(!m_karts[i]->getController()->isPlayerController()) return;
if(!m_kart_info[i].getSector()->isOnRoad()|| if(!m_kart_info[i].getTrackSector()->isOnRoad()||
m_karts[i]->getKartAnimation()) return; m_karts[i]->getKartAnimation()) return;
const AbstractKart *kart=m_karts[i]; const AbstractKart *kart=m_karts[i];
// If the kart can go in more than one directions from the current track // If the kart can go in more than one directions from the current track
// don't do any reverse message handling, since it is likely that there // don't do any reverse message handling, since it is likely that there
// will be one direction in which it isn't going backwards anyway. // will be one direction in which it isn't going backwards anyway.
int sector = m_kart_info[i].getSector()->getCurrentGraphNode(); int sector = m_kart_info[i].getTrackSector()->getCurrentGraphNode();
if(QuadGraph::get()->getNumberOfSuccessors(sector)>1) if(QuadGraph::get()->getNumberOfSuccessors(sector)>1)
return; return;

View File

@ -79,7 +79,7 @@ private:
float m_overall_distance; float m_overall_distance;
/** Stores the current graph node and track coordinates etc. */ /** Stores the current graph node and track coordinates etc. */
TrackSector m_current_sector; TrackSector m_track_sector;
/** Initialises all fields. */ /** Initialises all fields. */
KartInfo() { reset(); } KartInfo() { reset(); }
@ -92,14 +92,14 @@ private:
m_time_at_last_lap = 99999.9f; m_time_at_last_lap = 99999.9f;
m_estimated_finish = -1.0f; m_estimated_finish = -1.0f;
m_overall_distance = 0.0f; m_overall_distance = 0.0f;
m_current_sector.reset(); m_track_sector.reset();
} // reset } // reset
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/** Returns a pointer to the current node object. */ /** Returns a pointer to the current node object. */
TrackSector *getSector() {return &m_current_sector; } TrackSector *getTrackSector() {return &m_track_sector; }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/** Returns a pointer to the current node object. */ /** Returns a pointer to the current node object. */
const TrackSector *getSector() const {return &m_current_sector; } const TrackSector *getTrackSector() const {return &m_track_sector; }
}; };
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -133,7 +133,10 @@ public:
virtual void getKartsDisplayInfo( virtual void getKartsDisplayInfo(
std::vector<RaceGUIBase::KartIconDisplayInfo> *info) OVERRIDE; std::vector<RaceGUIBase::KartIconDisplayInfo> *info) OVERRIDE;
virtual void moveKartAfterRescue(AbstractKart* kart) OVERRIDE;
virtual unsigned int getNumberOfRescuePositions() const OVERRIDE;
virtual unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE;
virtual btTransform getRescueTransform(unsigned int index) const OVERRIDE;
virtual void reset() OVERRIDE; virtual void reset() OVERRIDE;
virtual void newLap(unsigned int kart_index) OVERRIDE; virtual void newLap(unsigned int kart_index) OVERRIDE;
@ -151,7 +154,7 @@ public:
* \param kart_index Index of the kart. */ * \param kart_index Index of the kart. */
bool isOnRoad(unsigned int kart_index) const bool isOnRoad(unsigned int kart_index) const
{ {
return m_kart_info[kart_index].getSector()->isOnRoad(); return m_kart_info[kart_index].getTrackSector()->isOnRoad();
} // isOnRoad } // isOnRoad
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -168,7 +171,7 @@ public:
* \param kart_index World index of the kart. */ * \param kart_index World index of the kart. */
TrackSector& getTrackSector(unsigned int kart_index) TrackSector& getTrackSector(unsigned int kart_index)
{ {
return m_kart_info[kart_index].m_current_sector; return m_kart_info[kart_index].m_track_sector;
} // getTrackSector } // getTrackSector
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -33,9 +33,9 @@
#include "tracks/track.hpp" #include "tracks/track.hpp"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
OverWorld::OverWorld() : LinearWorld() OverWorld::OverWorld() : WorldWithRank()
{ {
m_return_to_garage = false; m_return_to_garage = false;
m_stop_music_when_dialog_open = false; m_stop_music_when_dialog_open = false;
} // Overworld } // Overworld
@ -114,7 +114,7 @@ void OverWorld::update(float dt)
music_manager->getCurrentMusic()->startMusic(); music_manager->getCurrentMusic()->startMusic();
m_karts[0]->startEngineSFX(); m_karts[0]->startEngineSFX();
} }
LinearWorld::update(dt); WorldWithRank::update(dt);
const unsigned int kart_amount = m_karts.size(); const unsigned int kart_amount = m_karts.size();
// isn't it cool, on the overworld nitro is free! // isn't it cool, on the overworld nitro is free!
@ -135,6 +135,15 @@ void OverWorld::update(float dt)
} }
} // update } // update
//-----------------------------------------------------------------------------
/** This function is not used in the overworld race gui.
*/
void OverWorld::getKartsDisplayInfo(
std::vector<RaceGUIBase::KartIconDisplayInfo> *info)
{
assert(false);
} // getKartsDisplayInfo
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Override the base class method to change behavior. We don't want wrong /** Override the base class method to change behavior. We don't want wrong
* direction messages in the overworld since there is no direction there. * direction messages in the overworld since there is no direction there.
@ -190,96 +199,6 @@ void OverWorld::onFirePressed(Controller* who)
} // end for } // end for
} // onFirePressed } // onFirePressed
//-----------------------------------------------------------------------------
btTransform OverWorld::getClosestStartPoint(float currentKart_x,
float currentKart_z)
{
// find closest point to drop kart on
World *world = World::getWorld();
const int start_spots_amount =
world->getTrack()->getNumberOfStartPositions();
assert(start_spots_amount > 0);
int closest_id = -1;
float closest_distance = 999999999.0f;
for (int n=0; n<start_spots_amount; n++)
{
// no need for the overhead to compute exact distance with sqrt(),
// so using the 'manhattan' heuristic which will do fine enough.
const btTransform &s = world->getTrack()->getStartTransform(n);
const Vec3 &v = s.getOrigin();
float absDistance = fabs(currentKart_x - v.getX()) +
fabs(currentKart_z - v.getZ());
if (absDistance < closest_distance)
{
closest_distance = absDistance;
closest_id = n;
}
}
assert(closest_id != -1);
return world->getTrack()->getStartTransform(closest_id);
} // getClosestStartPoint
//-----------------------------------------------------------------------------
/** Moves a kart to its rescue position.
* \param kart The kart that was rescued.
*/
void OverWorld::moveKartAfterRescue(AbstractKart* kart)
{
moveKartAfterRescue(kart, 0);
} // moveKartAfterRescue(AbstractKart*)
//-----------------------------------------------------------------------------
void OverWorld::moveKartAfterRescue(AbstractKart* kart, float angle)
{
// find closest point to drop kart on
World *world = World::getWorld();
const int start_spots_amount =
world->getTrack()->getNumberOfStartPositions();
assert(start_spots_amount > 0);
const float currentKart_x = kart->getXYZ().getX();
const float currentKart_z = kart->getXYZ().getZ();
const btTransform& s = getClosestStartPoint(currentKart_x, currentKart_z);
const Vec3 &xyz = s.getOrigin();
kart->setXYZ(xyz);
kart->setRotation(s.getRotation());
//position kart from same height as in World::resetAllKarts
btTransform pos;
pos.setOrigin( kart->getXYZ()
+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f) );
pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), angle) );
kart->getBody()->setCenterOfMassTransform(pos);
//project kart to surface of track
bool kart_over_ground = m_track->findGround(kart);
if (kart_over_ground)
{
//add vertical offset so that the kart starts off above the track
float vertical_offset =
kart->getKartProperties()->getVertRescueOffset()
* kart->getKartHeight();
kart->getBody()->translate(btVector3(0, vertical_offset, 0));
}
else
{
Log::warn("overworld", "Invalid position after rescue for kart %s "
"on track %s.", (kart->getIdent().c_str()),
m_track->getIdent().c_str());
}
} // moveKartAfterRescue
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Called when a mouse click happens. If the click happened while the mouse /** Called when a mouse click happens. If the click happened while the mouse
* was hovering on top of a challenge, the kart will be teleported to * was hovering on top of a challenge, the kart will be teleported to
@ -293,14 +212,19 @@ void OverWorld::onMouseClick(int x, int y)
if(challenge) if(challenge)
{ {
// Use the 'get closest start point' rescue function
// from WorldWithRank by setting the kart's position to
// be the location of the challenge bubble.
AbstractKart* kart = getKart(0); AbstractKart* kart = getKart(0);
const btTransform& s = getClosestStartPoint(challenge->m_position.X, kart->setXYZ(challenge->m_position);
challenge->m_position.Z);
const Vec3 &xyz = s.getOrigin(); unsigned int index = getRescuePositionIndex(kart);
float angle = atan2(challenge->m_position.X - xyz[0], btTransform s = getRescueTransform(index);
challenge->m_position.Z - xyz[2]); const btVector3 &xyz = s.getOrigin();
kart->setXYZ(xyz); float angle = atan2(challenge->m_position.X - xyz[0],
moveKartAfterRescue(kart, angle); challenge->m_position.Z - xyz[2]);
s.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), angle) );
moveKartTo(kart, s);
return; return;
} }
} // onMouseClick } // onMouseClick

View File

@ -20,7 +20,7 @@
#include <vector> #include <vector>
#include "modes/linear_world.hpp" #include "modes/world_with_rank.hpp"
#include "utils/aligned_array.hpp" #include "utils/aligned_array.hpp"
#include "LinearMath/btTransform.h" #include "LinearMath/btTransform.h"
@ -32,7 +32,7 @@
* linear. * linear.
* \ingroup modes * \ingroup modes
*/ */
class OverWorld : public LinearWorld class OverWorld : public WorldWithRank
{ {
protected: protected:
@ -41,10 +41,6 @@ protected:
bool m_return_to_garage; bool m_return_to_garage;
void moveKartAfterRescue(AbstractKart* kart, float angle);
btTransform getClosestStartPoint(float currentKart_x, float currentKart_z);
public: public:
OverWorld(); OverWorld();
virtual ~OverWorld(); virtual ~OverWorld();
@ -52,7 +48,8 @@ public:
static void enterOverWorld(); static void enterOverWorld();
virtual void update(float delta) OVERRIDE; virtual void update(float delta) OVERRIDE;
virtual void getKartsDisplayInfo(
std::vector<RaceGUIBase::KartIconDisplayInfo> *info) OVERRIDE;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns if this race mode has laps. */ /** Returns if this race mode has laps. */
virtual bool raceHasLaps() OVERRIDE { return false; } virtual bool raceHasLaps() OVERRIDE { return false; }
@ -77,8 +74,6 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void scheduleSelectKart() { m_return_to_garage = true; } void scheduleSelectKart() { m_return_to_garage = true; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual void moveKartAfterRescue(AbstractKart* kart) OVERRIDE;
// ------------------------------------------------------------------------
virtual void onMouseClick(int x, int y) OVERRIDE; virtual void onMouseClick(int x, int y) OVERRIDE;
}; };

View File

@ -191,88 +191,7 @@ void SoccerWorld::getKartsDisplayInfo(
*/ */
} // getKartsDisplayInfo } // getKartsDisplayInfo
//----------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Moves a kart to its rescue position.
* \param kart The kart that was rescued.
*/
void SoccerWorld::moveKartAfterRescue(AbstractKart* kart)
{
// find closest point to drop kart on
World *world = World::getWorld();
const int start_spots_amount = world->getTrack()->getNumberOfStartPositions();
assert(start_spots_amount > 0);
float largest_accumulated_distance_found = -1;
int furthest_id_found = -1;
const float kart_x = kart->getXYZ().getX();
const float kart_z = kart->getXYZ().getZ();
for(int n=0; n<start_spots_amount; n++)
{
// no need for the overhead to compute exact distance with sqrt(),
// so using the 'manhattan' heuristic which will do fine enough.
const btTransform &s = world->getTrack()->getStartTransform(n);
const Vec3 &v=s.getOrigin();
float accumulatedDistance = .0f;
bool spawnPointClear = true;
for(unsigned int k=0; k<getCurrentNumKarts(); k++)
{
const AbstractKart *currentKart = World::getWorld()->getKart(k);
const float currentKart_x = currentKart->getXYZ().getX();
const float currentKartk_z = currentKart->getXYZ().getZ();
if(kart_x!=currentKart_x && kart_z !=currentKartk_z)
{
float absDistance = fabs(currentKart_x - v.getX()) +
fabs(currentKartk_z - v.getZ());
if(absDistance < CLEAR_SPAWN_RANGE)
{
spawnPointClear = false;
break;
}
accumulatedDistance += absDistance;
}
}
if(largest_accumulated_distance_found < accumulatedDistance && spawnPointClear)
{
furthest_id_found = n;
largest_accumulated_distance_found = accumulatedDistance;
}
}
assert(furthest_id_found != -1);
const btTransform &s = world->getTrack()->getStartTransform(furthest_id_found);
const Vec3 &xyz = s.getOrigin();
kart->setXYZ(xyz);
kart->setRotation(s.getRotation());
//position kart from same height as in World::resetAllKarts
btTransform pos;
pos.setOrigin(kart->getXYZ()+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f));
pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 0 /* angle */) );
kart->getBody()->setCenterOfMassTransform(pos);
//project kart to surface of track
bool kart_over_ground = m_track->findGround(kart);
if (kart_over_ground)
{
//add vertical offset so that the kart starts off above the track
float vertical_offset = kart->getKartProperties()->getVertRescueOffset() *
kart->getKartHeight();
kart->getBody()->translate(btVector3(0, vertical_offset, 0));
}
else
{
fprintf(stderr, "WARNING: invalid position after rescue for kart %s on track %s.\n",
(kart->getIdent().c_str()), m_track->getIdent().c_str());
}
} // moveKartAfterRescue
/** Set position and team for the karts */ /** Set position and team for the karts */
void SoccerWorld::initKartList() void SoccerWorld::initKartList()
{ {

View File

@ -64,7 +64,6 @@ public:
virtual void getKartsDisplayInfo( virtual void getKartsDisplayInfo(
std::vector<RaceGUIBase::KartIconDisplayInfo> *info); std::vector<RaceGUIBase::KartIconDisplayInfo> *info);
virtual bool raceHasLaps(){ return false; } virtual bool raceHasLaps(){ return false; }
virtual void moveKartAfterRescue(AbstractKart* kart);
virtual const std::string& getIdent() const; virtual const std::string& getIdent() const;

View File

@ -1,3 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart // SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 SuperTuxKart-Team // Copyright (C) 2006 SuperTuxKart-Team
// //
@ -477,83 +479,52 @@ void ThreeStrikesBattle::getKartsDisplayInfo(
} // getKartsDisplayInfo } // getKartsDisplayInfo
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Moves a kart to its rescue position. /** Determines the rescue position for a kart. The rescue position is the
* \param kart The kart that was rescued. * start position which is has the biggest accumulated distance to all other
* karts, and which has no other kart very close. The latter avoids dropping
* a kart on top of another kart.
* \param kart The kart that is going to be rescued.
* \returns The index of the start position to which the rescued kart
* should be moved to.
*/ */
void ThreeStrikesBattle::moveKartAfterRescue(AbstractKart* kart)
unsigned int ThreeStrikesBattle::getRescuePositionIndex(AbstractKart *kart)
{ {
// find closest point to drop kart on const int start_spots_amount = getTrack()->getNumberOfStartPositions();
World *world = World::getWorld();
const int start_spots_amount = world->getTrack()->getNumberOfStartPositions();
assert(start_spots_amount > 0); assert(start_spots_amount > 0);
float largest_accumulated_distance_found = -1; float largest_accumulated_distance_found = -1;
int furthest_id_found = -1; int furthest_id_found = -1;
const float kart_x = kart->getXYZ().getX();
const float kart_z = kart->getXYZ().getZ();
for(int n=0; n<start_spots_amount; n++) for(int n=0; n<start_spots_amount; n++)
{ {
// no need for the overhead to compute exact distance with sqrt(), const btTransform &s = getTrack()->getStartTransform(n);
// so using the 'manhattan' heuristic which will do fine enough.
const btTransform &s = world->getTrack()->getStartTransform(n);
const Vec3 &v=s.getOrigin(); const Vec3 &v=s.getOrigin();
float accumulatedDistance = .0f; float accumulated_distance = .0f;
bool spawnPointClear = true; bool spawn_point_clear = true;
for(unsigned int k=0; k<getCurrentNumKarts(); k++) for(unsigned int k=0; k<getCurrentNumKarts(); k++)
{ {
const AbstractKart *currentKart = World::getWorld()->getKart(k); if(kart->getWorldKartId()==k) continue;
const float currentKart_x = currentKart->getXYZ().getX(); float abs_distance2 = (getKart(k)->getXYZ()-v).length2_2d();
const float currentKartk_z = currentKart->getXYZ().getZ(); const float CLEAR_SPAWN_RANGE2 = 5*5;
if( abs_distance2 < CLEAR_SPAWN_RANGE2)
if(kart_x!=currentKart_x && kart_z !=currentKartk_z)
{ {
float absDistance = fabs(currentKart_x - v.getX()) + spawn_point_clear = false;
fabs(currentKartk_z - v.getZ()); break;
if(absDistance < CLEAR_SPAWN_RANGE)
{
spawnPointClear = false;
break;
}
accumulatedDistance += absDistance;
} }
accumulated_distance += sqrt(abs_distance2);
} }
if(largest_accumulated_distance_found < accumulatedDistance && spawnPointClear) if(accumulated_distance > largest_accumulated_distance_found &&
spawn_point_clear)
{ {
furthest_id_found = n; furthest_id_found = n;
largest_accumulated_distance_found = accumulatedDistance; largest_accumulated_distance_found = accumulated_distance;
} }
} }
assert(furthest_id_found != -1); assert(furthest_id_found != -1);
const btTransform &s = world->getTrack()->getStartTransform(furthest_id_found); return furthest_id_found;
const Vec3 &xyz = s.getOrigin(); } // getRescuePositionIndex
kart->setXYZ(xyz);
kart->setRotation(s.getRotation());
//position kart from same height as in World::resetAllKarts
btTransform pos;
pos.setOrigin(kart->getXYZ()+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f));
pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 0 /* angle */) );
kart->getBody()->setCenterOfMassTransform(pos);
//project kart to surface of track
bool kart_over_ground = m_track->findGround(kart);
if (kart_over_ground)
{
//add vertical offset so that the kart starts off above the track
float vertical_offset = kart->getKartProperties()->getVertRescueOffset() *
kart->getKartHeight();
kart->getBody()->translate(btVector3(0, vertical_offset, 0));
}
else
{
fprintf(stderr, "WARNING: invalid position after rescue for kart %s on track %s.\n",
(kart->getIdent().c_str()), m_track->getIdent().c_str());
}
} // moveKartAfterRescue

View File

@ -16,8 +16,8 @@
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef THREE_STRIKES_HPP #ifndef THREE_STRIKES_BATTLE_HPP
#define THREE_STRIKES_HPP #define THREE_STRIKES_BATTLE_HPP
#include "modes/world_with_rank.hpp" #include "modes/world_with_rank.hpp"
@ -28,8 +28,6 @@
#include <string> #include <string>
#define CLEAR_SPAWN_RANGE 5
class PhysicalObject; class PhysicalObject;
/** /**
@ -99,7 +97,7 @@ public:
virtual void getKartsDisplayInfo( virtual void getKartsDisplayInfo(
std::vector<RaceGUIBase::KartIconDisplayInfo> *info); std::vector<RaceGUIBase::KartIconDisplayInfo> *info);
virtual bool raceHasLaps(){ return false; } virtual bool raceHasLaps(){ return false; }
virtual void moveKartAfterRescue(AbstractKart* kart); virtual unsigned int getRescuePositionIndex(AbstractKart *kart);
virtual const std::string& getIdent() const; virtual const std::string& getIdent() const;

View File

@ -7,88 +7,4 @@
TutorialWorld::TutorialWorld() TutorialWorld::TutorialWorld()
{ {
m_stop_music_when_dialog_open = false; m_stop_music_when_dialog_open = false;
} } // TutorialWorld
// -----------------------------------------------------------------------------
void TutorialWorld::moveKartAfterRescue(AbstractKart* kart)
{
float angle = 0;
// find closest point to drop kart on
World *world = World::getWorld();
const int start_spots_amount =
world->getTrack()->getNumberOfStartPositions();
assert(start_spots_amount > 0);
const float currentKart_x = kart->getXYZ().getX();
const float currentKart_z = kart->getXYZ().getZ();
const btTransform& s = getClosestStartPoint(currentKart_x, currentKart_z);
const Vec3 &xyz = s.getOrigin();
kart->setXYZ(xyz);
kart->setRotation(s.getRotation());
//position kart from same height as in World::resetAllKarts
btTransform pos;
pos.setOrigin( kart->getXYZ()
+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f));
pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), angle) );
kart->getBody()->setCenterOfMassTransform(pos);
//project kart to surface of track
bool kart_over_ground = m_track->findGround(kart);
if (kart_over_ground)
{
//add vertical offset so that the kart starts off above the track
float vertical_offset =
kart->getKartProperties()->getVertRescueOffset()
* kart->getKartHeight();
kart->getBody()->translate(btVector3(0, vertical_offset, 0));
}
else
{
fprintf(stderr, "WARNING: invalid position after rescue for kart %s"
"on track %s.\n",
(kart->getIdent().c_str()), m_track->getIdent().c_str());
}
} // moveKartAfterRescue
// -----------------------------------------------------------------------------
btTransform TutorialWorld::getClosestStartPoint(float currentKart_x,
float currentKart_z)
{
// find closest point to drop kart on
World *world = World::getWorld();
const int start_spots_amount =
world->getTrack()->getNumberOfStartPositions();
assert(start_spots_amount > 0);
int closest_id = -1;
float closest_distance = 999999999.0f;
for (int n=0; n<start_spots_amount; n++)
{
// no need for the overhead to compute exact distance with sqrt(),
// so using the 'manhattan' heuristic which will do fine enough.
const btTransform &s = world->getTrack()->getStartTransform(n);
const Vec3 &v = s.getOrigin();
float absDistance = fabs(currentKart_x - v.getX()) +
fabs(currentKart_z - v.getZ());
if (absDistance < closest_distance)
{
closest_distance = absDistance;
closest_id = n;
}
}
assert(closest_id != -1);
return world->getTrack()->getStartTransform(closest_id);
} // getClosestStartPoint

View File

@ -6,13 +6,32 @@
class TutorialWorld : public StandardRace class TutorialWorld : public StandardRace
{ {
private:
btTransform getClosestStartPoint(float currentKart_x, float currentKart_z);
public: public:
TutorialWorld(); TutorialWorld();
virtual unsigned int getNumberOfRescuePositions() const OVERRIDE
{
// Don't use LinearWorld's function, but WorldWithRank, since the
// latter is based on rescuing to start positions
return WorldWithRank::getNumberOfRescuePositions();
}
// ------------------------------------------------------------------------
/** Determines the rescue position index of the specified kart. */
virtual unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE
{
// Don't use LinearWorld's function, but WorldWithRank, since the
// latter is based on rescuing to start positions
return WorldWithRank::getRescuePositionIndex(kart);
}
// ------------------------------------------------------------------------
/** Returns the bullet transformation for the specified rescue index. */
virtual btTransform getRescueTransform(unsigned int index) const OVERRIDE
{
// Don't use LinearWorld's function, but WorldWithRank, since the
// latter is based on rescuing to start positions
return WorldWithRank::getRescueTransform(index);
}
virtual void moveKartAfterRescue(AbstractKart* kart) OVERRIDE; }; // class TutorialWorld
};
#endif #endif

View File

@ -78,7 +78,22 @@ World* World::m_world = NULL;
* of all karts is set (i.e. in a normal race the arrival time for karts * of all karts is set (i.e. in a normal race the arrival time for karts
* will be estimated), highscore is updated, and the race result gui * will be estimated), highscore is updated, and the race result gui
* is being displayed. * is being displayed.
* Rescuing is handled via the three functions:
* getNumberOfRescuePositions() - which returns the number of rescue
* positions defined.
* getRescuePositionIndex(AbstractKart *kart) - which determines the
* index of the rescue position to be used for the given kart.
* getRescueTransform(unsigned int index) - which returns the transform
* (i.e. position and rotation) for the specified rescue
* position.
* This allows the world class to do some tests to make sure all rescue
* positions are valid (when started with --track-debug). It tries to
* place all karts on all rescue positions. If there are any problems
* (e.g. a rescue position not over terrain (perhaps because it is too
* low); or the rescue position is on a texture which will immediately
* trigger another rescue), a warning message will be printed.
*/ */
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Constructor. Note that in the constructor it is not possible to call any /** Constructor. Note that in the constructor it is not possible to call any
* functions that use World::getWorld(), since this is only defined * functions that use World::getWorld(), since this is only defined
@ -315,7 +330,7 @@ Controller* World::loadAIController(AbstractKart *kart)
controller = new SkiddingAI(kart); controller = new SkiddingAI(kart);
break; break;
default: default:
fprintf(stderr, "Warning: Unknown robot, using default.\n"); Log::warn("World", "Unknown AI, using default.");
controller = new SkiddingAI(kart); controller = new SkiddingAI(kart);
break; break;
} }
@ -465,65 +480,31 @@ void World::resetAllKarts()
// If track checking is requested, check all rescue positions if // If track checking is requested, check all rescue positions if
// they are heigh enough. // they are heigh enough.
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES && if(UserConfigParams::m_track_debug)
UserConfigParams::m_track_debug)
{ {
Vec3 eps = Vec3(0,1.5f*m_karts[0]->getKartHeight(),0); // Loop over all karts, in case that some karts are dfferent
for(unsigned int quad=0; quad<QuadGraph::get()->getNumNodes(); quad++)
{
const Quad &q = QuadGraph::get()->getQuadOfNode(quad);
const Vec3 center = q.getCenter();
// We have to test for all karts, since the karts have different
// heights and so things might change from kart to kart.
for(unsigned int kart_id=0; kart_id<m_karts.size(); kart_id++)
{
AbstractKart *kart = m_karts[kart_id];
kart->setXYZ(center);
btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f),
m_track->getAngle(quad) );
kart->setRotation(heading);
btTransform pos;
pos.setOrigin(center+eps);
pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f),
m_track->getAngle(quad)) );
kart->getBody()->setCenterOfMassTransform(pos);
bool kart_over_ground = m_track->findGround(kart);
if(kart_over_ground)
{
const Vec3 &xyz = kart->getTrans().getOrigin()
+ Vec3(0,0.3f,0);
if(dynamic_cast<Kart*>(kart))
dynamic_cast<Kart*>(kart)->getTerrainInfo()
->update(xyz);
const Material *material = kart->getMaterial();
if(!material || material->isDriveReset())
kart_over_ground = false;
}
if(!kart_over_ground)
{
printf("Kart '%s' not over quad '%d'\n",
kart->getIdent().c_str(), quad);
printf("Center point: %f %f %f\n",
center.getX(), center.getY(), center.getZ());
}
} // for kart_id<m_karts.size()
} // for quad < quad_graph.getNumNodes
for(unsigned int kart_id=0; kart_id<m_karts.size(); kart_id++) for(unsigned int kart_id=0; kart_id<m_karts.size(); kart_id++)
{ {
for(unsigned int rescue_pos=0;
rescue_pos<getNumberOfRescuePositions();
rescue_pos++)
{
btTransform t = getRescueTransform(rescue_pos);
// This will print out warnings if there is no terrain under
// the kart, or the kart is being dropped on a reset texture
moveKartTo(m_karts[kart_id], t);
} // rescue_pos<getNumberOfRescuePositions
// Reset the karts back to the original start position. // Reset the karts back to the original start position.
// This call is a bit of an overkill, but setting the correct // This call is a bit of an overkill, but setting the correct
// transforms, positions, motion state is a bit of a hassle. // transforms, positions, motion state is a bit of a hassle.
m_karts[kart_id]->reset(); m_karts[kart_id]->reset();
} } // for kart_id<m_karts.size()
} // if m_track_debug } // if m_track_debug
m_schedule_pause = false; m_schedule_pause = false;
m_schedule_unpause = false; m_schedule_unpause = false;
@ -540,13 +521,12 @@ void World::resetAllKarts()
if (!kart_over_ground) if (!kart_over_ground)
{ {
fprintf(stderr, Log::error("World",
"ERROR: no valid starting position for kart %d " "No valid starting position for kart %d on track %s.",
"on track %s.\n", (int)(i-m_karts.begin()), m_track->getIdent().c_str());
(int)(i-m_karts.begin()), m_track->getIdent().c_str());
if (UserConfigParams::m_artist_debug_mode) if (UserConfigParams::m_artist_debug_mode)
{ {
fprintf(stderr, "Activating fly mode.\n"); Log::warn("World", "Activating fly mode.");
(*i)->flyUp(); (*i)->flyUp();
continue; continue;
} }
@ -592,14 +572,14 @@ void World::resetAllKarts()
&normal); &normal);
if(!material) if(!material)
{ {
fprintf(stderr, Log::error("World",
"ERROR: no valid starting position for " "No valid starting position for kart %d "
"kart %d on track %s.\n", "on track %s.",
(int)(i-m_karts.begin()), (int)(i-m_karts.begin()),
m_track->getIdent().c_str()); m_track->getIdent().c_str());
if (UserConfigParams::m_artist_debug_mode) if (UserConfigParams::m_artist_debug_mode)
{ {
fprintf(stderr, "Activating fly mode.\n"); Log::warn("World", "Activating fly mode.");
(*i)->flyUp(); (*i)->flyUp();
continue; continue;
} }
@ -631,6 +611,44 @@ void World::resetAllKarts()
} }
} // resetAllKarts } // resetAllKarts
// ----------------------------------------------------------------------------
/** Places a kart that is rescued. It calls getRescuePositionIndex to find
* to which rescue position the kart should be moved, then getRescueTransform
* to get the position and rotation of this rescue position, and then moves
* the kart.
* \param kart The kart that is rescued.
*/
void World::moveKartAfterRescue(AbstractKart* kart)
{
unsigned int index = getRescuePositionIndex(kart);
btTransform t = getRescueTransform(index);
moveKartTo(kart, t);
} // moveKartAfterRescue
// ----------------------------------------------------------------------------
/** Places the kart at a given position and rotation.
* \param kart The kart to be moved.
* \param transform
*/
void World::moveKartTo(AbstractKart* kart, const btTransform &transform)
{
btTransform pos(transform);
// Move the kart
Vec3 xyz = pos.getOrigin() + btVector3(0, 0.5f*kart->getKartHeight(),0.0f);
pos.setOrigin(xyz);
kart->setXYZ(xyz);
kart->setRotation(pos.getRotation());
kart->getBody()->setCenterOfMassTransform(pos);
// Project kart to surface of track
// This will set the physics transform
m_track->findGround(kart);
} // moveKartTo
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void World::schedulePause(Phase phase) void World::schedulePause(Phase phase)
{ {
@ -727,10 +745,11 @@ void World::updateWorld(float dt)
StateManager::get()->createActivePlayer(unlock_manager->getCurrentPlayer(), StateManager::get()->createActivePlayer(unlock_manager->getCurrentPlayer(),
device, NULL); device, NULL);
if (kart_properties_manager->getKart(UserConfigParams::m_default_kart) == NULL) if (!kart_properties_manager->getKart(UserConfigParams::m_default_kart))
{ {
fprintf(stderr, "[MainMenuScreen] WARNING: cannot find kart '%s', will revert to default\n", Log::warn("World",
UserConfigParams::m_default_kart.c_str()); "Cannot find kart '%s', will revert to default.",
UserConfigParams::m_default_kart.c_str());
UserConfigParams::m_default_kart.revertToDefaults(); UserConfigParams::m_default_kart.revertToDefaults();
} }
race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart); race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart);
@ -903,11 +922,11 @@ void World::updateHighscores(int* best_highscore_rank, int* best_finish_time,
// the kart location data is wrong // the kart location data is wrong
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Error, incorrect kart positions:\n"); Log::error("World", "Incorrect kart positions:");
for (unsigned int i=0; i<m_karts.size(); i++ ) for (unsigned int i=0; i<m_karts.size(); i++ )
{ {
fprintf(stderr, "i=%d position %d\n",i, Log::error("World", "i=%d position %d.",i,
m_karts[i]->getPosition()); m_karts[i]->getPosition());
} }
#endif #endif
continue; continue;

View File

@ -33,6 +33,8 @@
#include "states_screens/state_manager.hpp" #include "states_screens/state_manager.hpp"
#include "utils/random_generator.hpp" #include "utils/random_generator.hpp"
#include "LinearMath/btTransform.h"
class AbstractKart; class AbstractKart;
class btRigidBody; class btRigidBody;
class Controller; class Controller;
@ -156,6 +158,7 @@ protected:
virtual void update(float dt); virtual void update(float dt);
virtual void createRaceGUI(); virtual void createRaceGUI();
void updateTrack(float dt); void updateTrack(float dt);
void moveKartTo(AbstractKart* kart, const btTransform &t);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Used for AI karts that are still racing when all player kart finished. /** Used for AI karts that are still racing when all player kart finished.
* Generally it should estimate the arrival time for those karts, but as * Generally it should estimate the arrival time for those karts, but as
@ -192,13 +195,19 @@ public:
/** Each game mode should have a unique identifier. Override /** Each game mode should have a unique identifier. Override
* this method in child classes to provide it. */ * this method in child classes to provide it. */
virtual const std::string& virtual const std::string& getIdent() const = 0;
getIdent() const = 0;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Since each mode will have a different way of deciding where a rescued /** Returns the number of rescue positions on a given track and game
* kart is dropped, this method will be called and each mode can implement * mode. */
* it. */ virtual unsigned int getNumberOfRescuePositions() const OVERRIDE = 0;
virtual void moveKartAfterRescue(AbstractKart* kart) = 0; // ------------------------------------------------------------------------
/** Determines the rescue position index of the specified kart. */
virtual unsigned int getRescuePositionIndex(AbstractKart *kart) = 0;
// ------------------------------------------------------------------------
/** Returns the bullet transformation for the specified rescue index. */
virtual btTransform getRescueTransform(unsigned int index) const = 0;
// ------------------------------------------------------------------------
void moveKartAfterRescue(AbstractKart* kart);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Called when it is needed to know whether this kind of race involves /** Called when it is needed to know whether this kind of race involves
* counting laps. */ * counting laps. */

View File

@ -18,7 +18,9 @@
#include "modes/world_with_rank.hpp" #include "modes/world_with_rank.hpp"
#include "karts/abstract_kart.hpp" #include "karts/abstract_kart.hpp"
#include "karts/kart_properties.hpp"
#include "race/history.hpp" #include "race/history.hpp"
#include "tracks/track.hpp"
#include <iostream> #include <iostream>
@ -120,3 +122,53 @@ void WorldWithRank::endSetKartPositions()
} // endSetKartPositions } // endSetKartPositions
//-----------------------------------------------------------------------------
/** WorldWithRank uses the start position as rescue positions. So return
* the number of start positions.
*/
unsigned int WorldWithRank::getNumberOfRescuePositions() const
{
return getTrack()->getNumberOfStartPositions();
} // getNumberOfRescuePositions
// ----------------------------------------------------------------------------
/** Finds the starting position which is closest to the kart.
* \param kart The kart for which a rescue position needs to be determined.
*/
unsigned int WorldWithRank::getRescuePositionIndex(AbstractKart *kart)
{
// find closest point to drop kart on
const int start_spots_amount = getNumberOfRescuePositions();
assert(start_spots_amount > 0);
int closest_id = -1;
float closest_distance = 999999999.0f;
for (int n=0; n<start_spots_amount; n++)
{
const btTransform &s = getTrack()->getStartTransform(n);
const Vec3 &v = s.getOrigin();
float abs_distance = (v - kart->getXYZ()).length();
if (abs_distance < closest_distance)
{
closest_distance = abs_distance;
closest_id = n;
}
}
assert(closest_id != -1);
return closest_id;
} // getRescuePositionIndex
// ----------------------------------------------------------------------------
/** Returns the start transform with the give index.
* \param rescue_pos Index of the start position to be returned.
* \returns The transform of the corresponding start position.
*/
btTransform WorldWithRank::getRescueTransform(unsigned int rescue_pos) const
{
return getTrack()->getStartTransform(rescue_pos);
} // getRescueTransform

View File

@ -28,7 +28,10 @@ class AbstractKart;
* A WorldWithRank is a world where the karts are ranked. This is the base * A WorldWithRank is a world where the karts are ranked. This is the base
* class for races and battle modes - all of which rank the kart. * class for races and battle modes - all of which rank the kart.
* A class using this as a subclass must call setKartPosition(kart id, position) * A class using this as a subclass must call setKartPosition(kart id, position)
* and this class is used to access the ranks from other objects. * and this class is used to access the ranks from other objects. This class
* adds a convenient rescue implementation: a kart is rescued to the closest
* start point. This is useful for battle, soccer, ... modes. Linear world
* defines its own rescue functions and will overwrite this.
* \ingroup modes * \ingroup modes
*/ */
class WorldWithRank : public World class WorldWithRank : public World
@ -51,6 +54,8 @@ protected:
bool m_position_setting_initialised; bool m_position_setting_initialised;
#endif #endif
unsigned int getClosestStartPoint(AbstractKart *kart);
public: public:
WorldWithRank() : World() {} WorldWithRank() : World() {}
/** call just after instanciating. can't be moved to the contructor as child /** call just after instanciating. can't be moved to the contructor as child
@ -64,8 +69,13 @@ public:
bool setKartPosition(unsigned int kart_id, bool setKartPosition(unsigned int kart_id,
unsigned int position); unsigned int position);
void endSetKartPositions(); void endSetKartPositions();
AbstractKart* getKartAtPosition(unsigned int p) const; AbstractKart* getKartAtPosition(unsigned int p) const;
virtual unsigned int getNumberOfRescuePositions() const OVERRIDE;
virtual unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE;
virtual btTransform getRescueTransform(unsigned int index) const OVERRIDE;
}; // WorldWithRank }; // WorldWithRank
#endif #endif

View File

@ -124,8 +124,7 @@ void ClientLobbyRoomProtocol::update()
{ {
NetworkString ns; NetworkString ns;
// 1 (connection request), 4 (size of id), global id // 1 (connection request), 4 (size of id), global id
ns.ai8(1).ai8(4).ai32(Online::CurrentUser::acquire()->getUserID()); ns.ai8(1).ai8(4).ai32(Online::CurrentUser::get()->getUserID());
Online::CurrentUser::release();
m_listener->sendMessage(this, ns); m_listener->sendMessage(this, ns);
m_state = REQUESTING_CONNECTION; m_state = REQUESTING_CONNECTION;
} break; } break;
@ -175,9 +174,8 @@ void ClientLobbyRoomProtocol::newPlayer(Event* event)
uint32_t global_id = event->data.gui32(1); uint32_t global_id = event->data.gui32(1);
uint8_t race_id = event->data.gui8(6); uint8_t race_id = event->data.gui8(6);
if (global_id == Online::CurrentUser::acquire()->getUserID()) if (global_id == Online::CurrentUser::get()->getUserID())
{ {
Online::CurrentUser::release();
Log::error("ClientLobbyRoomProtocol", "The server notified me that i'm a new player in the room (not normal)."); Log::error("ClientLobbyRoomProtocol", "The server notified me that i'm a new player in the room (not normal).");
} }
else if (m_setup->getProfile(race_id) == NULL || m_setup->getProfile(global_id) == NULL) else if (m_setup->getProfile(race_id) == NULL || m_setup->getProfile(global_id) == NULL)
@ -247,17 +245,15 @@ void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
STKPeer* peer = *(event->peer); STKPeer* peer = *(event->peer);
uint32_t global_id = event->data.gui32(8); uint32_t global_id = event->data.gui32(8);
if (global_id == Online::CurrentUser::acquire()->getUserID()) if (global_id == Online::CurrentUser::get()->getUserID())
{ {
Online::CurrentUser::release();
Log::info("ClientLobbyRoomProtocol", "The server accepted the connection."); Log::info("ClientLobbyRoomProtocol", "The server accepted the connection.");
// self profile // self profile
NetworkPlayerProfile* profile = new NetworkPlayerProfile(); NetworkPlayerProfile* profile = new NetworkPlayerProfile();
profile->kart_name = ""; profile->kart_name = "";
profile->race_id = event->data.gui8(1); profile->race_id = event->data.gui8(1);
profile->user_profile = Online::CurrentUser::acquire(); profile->user_profile = Online::CurrentUser::get();
Online::CurrentUser::release();
m_setup->addPlayer(profile); m_setup->addPlayer(profile);
// connection token // connection token
uint32_t token = event->data.gui32(3); uint32_t token = event->data.gui32(3);

View File

@ -51,10 +51,8 @@ void GetPeerAddress::asynchronousUpdate()
{ {
m_request = new Online::XMLRequest(); m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID()); m_request->setParameter("id",Online::CurrentUser::get()->getUserID());
Online::CurrentUser::release(); m_request->setParameter("token",Online::CurrentUser::get()->getToken());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
Online::CurrentUser::release();
m_request->setParameter("peer_id",m_peer_id); m_request->setParameter("peer_id",m_peer_id);
m_request->setParameter("action","get"); m_request->setParameter("action","get");

View File

@ -47,10 +47,8 @@ void HidePublicAddress::asynchronousUpdate()
{ {
m_request = new Online::XMLRequest(); m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID()); m_request->setParameter("id",Online::CurrentUser::get()->getUserID());
Online::CurrentUser::release(); m_request->setParameter("token",Online::CurrentUser::get()->getToken());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
Online::CurrentUser::release();
m_request->setParameter("action","unset"); m_request->setParameter("action","unset");
Online::HTTPManager::get()->addRequest(m_request); Online::HTTPManager::get()->addRequest(m_request);

View File

@ -49,10 +49,8 @@ void QuickJoinProtocol::asynchronousUpdate()
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
m_request = new Online::XMLRequest(); m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID()); m_request->setParameter("id",Online::CurrentUser::get()->getUserID());
Online::CurrentUser::release(); m_request->setParameter("token",Online::CurrentUser::get()->getToken());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
Online::CurrentUser::release();
m_request->setParameter("action","quick-join"); m_request->setParameter("action","quick-join");
Online::HTTPManager::get()->addRequest(m_request); Online::HTTPManager::get()->addRequest(m_request);

View File

@ -49,10 +49,8 @@ void RequestConnection::asynchronousUpdate()
{ {
m_request = new Online::CurrentUser::ServerJoinRequest(); m_request = new Online::CurrentUser::ServerJoinRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID()); m_request->setParameter("id",Online::CurrentUser::get()->getUserID());
Online::CurrentUser::release(); m_request->setParameter("token",Online::CurrentUser::get()->getToken());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
Online::CurrentUser::release();
m_request->setParameter("server_id",m_server_id); m_request->setParameter("server_id",m_server_id);
m_request->setParameter("action","request-connection"); m_request->setParameter("action","request-connection");

View File

@ -116,10 +116,8 @@ void ServerLobbyRoomProtocol::update()
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
Online::XMLRequest* request = new Online::XMLRequest(); Online::XMLRequest* request = new Online::XMLRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
request->setParameter("id",Online::CurrentUser::acquire()->getUserID()); request->setParameter("id",Online::CurrentUser::get()->getUserID());
Online::CurrentUser::release(); request->setParameter("token",Online::CurrentUser::get()->getToken());
request->setParameter("token",Online::CurrentUser::acquire()->getToken());
Online::CurrentUser::release();
request->setParameter("address",addr.ip); request->setParameter("address",addr.ip);
request->setParameter("port",addr.port); request->setParameter("port",addr.port);
request->setParameter("action","poll-connection-requests"); request->setParameter("action","poll-connection-requests");

View File

@ -48,10 +48,8 @@ void ShowPublicAddress::asynchronousUpdate()
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
m_request = new Online::XMLRequest(); m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID()); m_request->setParameter("id",Online::CurrentUser::get()->getUserID());
Online::CurrentUser::release(); m_request->setParameter("token",Online::CurrentUser::get()->getToken());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
Online::CurrentUser::release();
m_request->setParameter("address",addr.ip); m_request->setParameter("address",addr.ip);
m_request->setParameter("port",addr.port); m_request->setParameter("port",addr.port);
m_request->setParameter("action","set"); m_request->setParameter("action","set");

View File

@ -103,8 +103,7 @@ void StartGameProtocol::update()
// have to add self first // have to add self first
for (unsigned int i = 0; i < players.size(); i++) for (unsigned int i = 0; i < players.size(); i++)
{ {
bool is_me = (players[i]->user_profile == Online::CurrentUser::acquire()); bool is_me = (players[i]->user_profile == Online::CurrentUser::get());
Online::CurrentUser::release();
if (is_me) if (is_me)
{ {
NetworkPlayerProfile* profile = players[i]; NetworkPlayerProfile* profile = players[i];
@ -128,8 +127,7 @@ void StartGameProtocol::update()
} }
for (unsigned int i = 0; i < players.size(); i++) for (unsigned int i = 0; i < players.size(); i++)
{ {
bool is_me = (players[i]->user_profile == Online::CurrentUser::acquire()); bool is_me = (players[i]->user_profile == Online::CurrentUser::get());
Online::CurrentUser::release();
NetworkPlayerProfile* profile = players[i]; NetworkPlayerProfile* profile = players[i];
RemoteKartInfo rki(profile->race_id, profile->kart_name, RemoteKartInfo rki(profile->race_id, profile->kart_name,
profile->user_profile->getUserName(), profile->race_id, !is_me); profile->user_profile->getUserName(), profile->race_id, !is_me);

View File

@ -47,10 +47,8 @@ void StartServer::asynchronousUpdate()
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
m_request = new Online::XMLRequest(); m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID()); m_request->setParameter("id",Online::CurrentUser::get()->getUserID());
Online::CurrentUser::release(); m_request->setParameter("token",Online::CurrentUser::get()->getToken());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
Online::CurrentUser::release();
m_request->setParameter("address",addr.ip); m_request->setParameter("address",addr.ip);
m_request->setParameter("port",addr.port); m_request->setParameter("port",addr.port);
m_request->setParameter("max_players",UserConfigParams::m_server_max_players); m_request->setParameter("max_players",UserConfigParams::m_server_max_players);

View File

@ -47,10 +47,8 @@ void StopServer::asynchronousUpdate()
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
m_request = new Online::XMLRequest(); m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID()); m_request->setParameter("id",Online::CurrentUser::get()->getUserID());
Online::CurrentUser::release(); m_request->setParameter("token",Online::CurrentUser::get()->getToken());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
Online::CurrentUser::release();
m_request->setParameter("address",addr.ip); m_request->setParameter("address",addr.ip);
m_request->setParameter("port",addr.port); m_request->setParameter("port",addr.port);
m_request->setParameter("action","stop-server"); m_request->setParameter("action","stop-server");

View File

@ -28,54 +28,55 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
using namespace Online;
namespace Online{ namespace Online{
static Synchronised<CurrentUser*> user_singleton(NULL); static CurrentUser* current_user_singleton(NULL);
CurrentUser* CurrentUser::acquire() CurrentUser* CurrentUser::get()
{ {
user_singleton.lock(); if (current_user_singleton == NULL)
CurrentUser * user = user_singleton.getData(); current_user_singleton = new CurrentUser();
if (user == NULL) return current_user_singleton;
{
user_singleton.unlock();
user = new CurrentUser();
user_singleton.setAtomic(user);
user_singleton.lock();
}
return user;
}
void CurrentUser::release()
{
user_singleton.unlock();
} }
void CurrentUser::deallocate() void CurrentUser::deallocate()
{ {
user_singleton.lock(); delete current_user_singleton;
CurrentUser* user = user_singleton.getData(); current_user_singleton = NULL;
delete user;
user = NULL;
user_singleton.unlock();
} // deallocate } // deallocate
// ============================================================================ // ============================================================================
CurrentUser::CurrentUser(){ CurrentUser::CurrentUser()
m_state = US_SIGNED_OUT; : User("",0)
m_id = 0; {
m_name = ""; setUserState (US_SIGNED_OUT);
m_token = ""; setToken("");
m_save_session = false; setSaveSession(false);
} }
// ============================================================================ // ============================================================================
XMLRequest * CurrentUser::requestSignUp( const irr::core::stringw &username, const XMLRequest * CurrentUser::requestRecovery( const irr::core::stringw &username,
const irr::core::stringw &password, const irr::core::stringw &email)
const irr::core::stringw &password_confirm,
const irr::core::stringw &email,
bool terms)
{ {
assert(m_state == US_SIGNED_OUT || m_state == US_GUEST); assert(getUserState() == US_SIGNED_OUT || getUserState() == US_GUEST);
XMLRequest * request = new XMLRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
request->setParameter("action", std::string("recovery"));
request->setParameter("username", username);
request->setParameter("email", email);
HTTPManager::get()->addRequest(request);
return request;
}
// ============================================================================
const 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(getUserState() == US_SIGNED_OUT || getUserState() == US_GUEST);
XMLRequest * request = new XMLRequest(); XMLRequest * request = new XMLRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php"); request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
request->setParameter("action", std::string("register")); request->setParameter("action", std::string("register"));
@ -89,10 +90,10 @@ namespace Online{
} }
// ============================================================================ // ============================================================================
CurrentUser::SignInRequest * CurrentUser::requestSavedSession() const CurrentUser::SignInRequest * CurrentUser::requestSavedSession()
{ {
SignInRequest * request = NULL; SignInRequest * request = NULL;
if(m_state != US_SIGNED_IN && UserConfigParams::m_saved_session) if(getUserState() != US_SIGNED_IN && UserConfigParams::m_saved_session)
{ {
request = new SignInRequest(); request = new SignInRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php"); request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
@ -100,7 +101,7 @@ namespace Online{
request->setParameter("userid", UserConfigParams::m_saved_user); request->setParameter("userid", UserConfigParams::m_saved_user);
request->setParameter("token", UserConfigParams::m_saved_token.c_str()); request->setParameter("token", UserConfigParams::m_saved_token.c_str());
HTTPManager::get()->addRequest(request); HTTPManager::get()->addRequest(request);
m_state = US_SIGNING_IN; setUserState (US_SIGNING_IN);
} }
return request; return request;
} }
@ -109,8 +110,8 @@ namespace Online{
const irr::core::stringw &password, const irr::core::stringw &password,
bool save_session, bool request_now) bool save_session, bool request_now)
{ {
assert(m_state == US_SIGNED_OUT); assert(getUserState() == US_SIGNED_OUT);
m_save_session = save_session; setSaveSession(save_session);
SignInRequest * request = new SignInRequest(); SignInRequest * request = new SignInRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php"); request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
request->setParameter("action",std::string("connect")); request->setParameter("action",std::string("connect"));
@ -119,7 +120,7 @@ namespace Online{
if (request_now) if (request_now)
{ {
HTTPManager::get()->addRequest(request); HTTPManager::get()->addRequest(request);
m_state = US_SIGNING_IN; setUserState (US_SIGNING_IN);
} }
return request; return request;
} }
@ -128,39 +129,44 @@ namespace Online{
{ {
if (input->isSuccess()) if (input->isSuccess())
{ {
int token_fetched = input->getResult()->get("token", &m_token); std::string token("");
int username_fetched = input->getResult()->get("username", &m_name); int token_fetched = input->getResult()->get("token", &token);
int userid_fetched = input->getResult()->get("userid", &m_id); setToken(token);
irr::core::stringw username("");
int username_fetched = input->getResult()->get("username", &username);
setUserName(username);
uint32_t userid(0);
int userid_fetched = input->getResult()->get("userid", &userid);
setUserID(userid);
assert(token_fetched && username_fetched && userid_fetched); assert(token_fetched && username_fetched && userid_fetched);
m_state = US_SIGNED_IN; setUserState (US_SIGNED_IN);
if(m_save_session) if(getSaveSession())
{ {
UserConfigParams::m_saved_user = m_id; UserConfigParams::m_saved_user = getUserID();
UserConfigParams::m_saved_token = m_token; UserConfigParams::m_saved_token = getToken();
UserConfigParams::m_saved_session = true; UserConfigParams::m_saved_session = true;
m_save_session = false;
} }
} }
else else
m_state = US_SIGNED_OUT; setUserState (US_SIGNED_OUT);
} }
void CurrentUser::SignInRequest::callback() void CurrentUser::SignInRequest::callback()
{ {
CurrentUser::acquire()->signIn(this); CurrentUser::get()->signIn(this);
CurrentUser::release();
} }
// ============================================================================ // ============================================================================
CurrentUser::ServerCreationRequest * CurrentUser::requestServerCreation(const irr::core::stringw &name, int max_players) const CurrentUser::ServerCreationRequest * CurrentUser::requestServerCreation( const irr::core::stringw &name,
int max_players)
{ {
assert(m_state == US_SIGNED_IN); assert(getUserState() == US_SIGNED_IN);
ServerCreationRequest * request = new ServerCreationRequest(); ServerCreationRequest * request = new ServerCreationRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php"); request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
request->setParameter("action", std::string("create_server")); request->setParameter("action", std::string("create_server"));
request->setParameter("token", m_token); request->setParameter("token", getToken());
request->setParameter("userid", m_id); request->setParameter("userid", getUserID());
request->setParameter("name", name); request->setParameter("name", name);
request->setParameter("max_players", max_players); request->setParameter("max_players", max_players);
HTTPManager::get()->addRequest(request); HTTPManager::get()->addRequest(request);
@ -172,22 +178,21 @@ namespace Online{
if(isSuccess()) if(isSuccess())
{ {
Server * server = new Server(*getResult()->getNode("server")); Server * server = new Server(*getResult()->getNode("server"));
ServersManager::acquire()->addServer(server); ServersManager::get()->addServer(server);
ServersManager::release();
m_created_server_id.setAtomic(server->getServerId()); m_created_server_id.setAtomic(server->getServerId());
} }
} }
// ============================================================================ // ============================================================================
CurrentUser::SignOutRequest * CurrentUser::requestSignOut(){ const CurrentUser::SignOutRequest * CurrentUser::requestSignOut(){
assert(m_state == US_SIGNED_IN || m_state == US_GUEST); assert(getUserState() == US_SIGNED_IN || getUserState() == US_GUEST);
SignOutRequest * request = new SignOutRequest(); SignOutRequest * request = new SignOutRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php"); request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
request->setParameter("action",std::string("disconnect")); request->setParameter("action",std::string("disconnect"));
request->setParameter("token",m_token); request->setParameter("token", getToken());
request->setParameter("userid",m_id); request->setParameter("userid", getUserID());
HTTPManager::get()->addRequest(request); HTTPManager::get()->addRequest(request);
m_state = US_SIGNING_OUT; setUserState (US_SIGNING_OUT);
return request; return request;
} }
@ -197,10 +202,10 @@ namespace Online{
{ {
Log::warn("CurrentUser::signOut", "%s", _("There were some connection issues while signing out. Report a bug if this caused issues.")); Log::warn("CurrentUser::signOut", "%s", _("There were some connection issues while signing out. Report a bug if this caused issues."));
} }
m_token = ""; setToken("");
m_name = ""; setUserName("");
m_id = 0; setUserID(0);
m_state = US_SIGNED_OUT; setUserState (US_SIGNED_OUT);
UserConfigParams::m_saved_user = 0; UserConfigParams::m_saved_user = 0;
UserConfigParams::m_saved_token = ""; UserConfigParams::m_saved_token = "";
UserConfigParams::m_saved_session = false; UserConfigParams::m_saved_session = false;
@ -208,8 +213,7 @@ namespace Online{
void CurrentUser::SignOutRequest::callback() void CurrentUser::SignOutRequest::callback()
{ {
CurrentUser::acquire()->signOut(this); CurrentUser::get()->signOut(this);
CurrentUser::release();
} }
// ============================================================================ // ============================================================================
@ -217,12 +221,12 @@ namespace Online{
CurrentUser::ServerJoinRequest * CurrentUser::requestServerJoin(uint32_t server_id, CurrentUser::ServerJoinRequest * CurrentUser::requestServerJoin(uint32_t server_id,
bool request_now) bool request_now)
{ {
assert(m_state == US_SIGNED_IN || m_state == US_GUEST); assert(getUserState() == US_SIGNED_IN || getUserState() == US_GUEST);
ServerJoinRequest * request = new ServerJoinRequest(); ServerJoinRequest * request = new ServerJoinRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
request->setParameter("action",std::string("request-connection")); request->setParameter("action",std::string("request-connection"));
request->setParameter("token", m_token); request->setParameter("token", getToken());
request->setParameter("id", m_id); request->setParameter("id", getUserID());
request->setParameter("server_id", server_id); request->setParameter("server_id", server_id);
if (request_now) if (request_now)
HTTPManager::get()->addRequest(request); HTTPManager::get()->addRequest(request);
@ -235,20 +239,18 @@ namespace Online{
{ {
uint32_t server_id; uint32_t server_id;
getResult()->get("serverid", &server_id); getResult()->get("serverid", &server_id);
ServersManager::acquire()->setJoinedServer(server_id); ServersManager::get()->setJoinedServer(server_id);
ServersManager::release();
} }
//FIXME needs changes for actual valid joining //FIXME needs changes for actual valid joining
} }
// ============================================================================ // ============================================================================
irr::core::stringw CurrentUser::getUserName() const const irr::core::stringw CurrentUser::getUserName() const
{ {
if((m_state == US_SIGNED_IN ) || (m_state == US_GUEST)) if((getUserState() == US_SIGNED_IN ) || (getUserState() == US_GUEST))
return m_name; return User::getUserName();
else else
return _("Currently not signed in"); return _("Currently not signed in");
} }
} // namespace Online } // namespace Online

View File

@ -23,6 +23,7 @@
#include "online/server.hpp" #include "online/server.hpp"
#include "online/user.hpp" #include "online/user.hpp"
#include "utils/types.hpp" #include "utils/types.hpp"
#include "utils/synchronised.hpp"
#include <irrString.h> #include <irrString.h>
@ -76,7 +77,7 @@ namespace Online{
Synchronised<uint32_t> m_created_server_id; Synchronised<uint32_t> m_created_server_id;
public: public:
ServerCreationRequest() : XMLRequest(RT_SERVER_CREATION) {} ServerCreationRequest() : XMLRequest(RT_SERVER_CREATION) {}
uint32_t getCreatedServerID() {return m_created_server_id.getAtomic();} const uint32_t getCreatedServerID() const {return m_created_server_id.getAtomic();}
}; };
class ServerJoinRequest : public XMLRequest { class ServerJoinRequest : public XMLRequest {
@ -87,9 +88,15 @@ namespace Online{
private: private:
std::string m_token; Synchronised<std::string> m_token;
bool m_save_session; Synchronised<bool> m_save_session;
UserState m_state; Synchronised<UserState> m_state;
bool getSaveSession() const { return m_save_session.getAtomic(); }
void setUserState (UserState user_state) { m_state.setAtomic(user_state); }
void setSaveSession (bool save_session) { m_save_session.setAtomic(save_session); }
void setToken (const std::string & token) { m_token.setAtomic(token); }
CurrentUser(); CurrentUser();
@ -98,35 +105,34 @@ namespace Online{
void createServer (const ServerCreationRequest * input); void createServer (const ServerCreationRequest * input);
public: public:
//Singleton /**Singleton */
static CurrentUser* acquire(); static CurrentUser * get();
static void release(); static void deallocate();
static void deallocate();
SignInRequest * requestSavedSession(); const SignInRequest * requestSavedSession();
SignInRequest * requestSignIn( const irr::core::stringw &username, SignInRequest * requestSignIn( const irr::core::stringw &username,
const irr::core::stringw &password, const irr::core::stringw &password,
bool save_session, bool save_session,
bool request_now = true); bool request_now = true);
SignOutRequest * requestSignOut(); const SignOutRequest * requestSignOut();
ServerCreationRequest * requestServerCreation( const irr::core::stringw &name, int max_players); const ServerCreationRequest * requestServerCreation(const irr::core::stringw &name, int max_players);
ServerJoinRequest * requestServerJoin( uint32_t server_id, bool request_now = true); ServerJoinRequest * requestServerJoin(uint32_t server_id, bool request_now = true);
// Register /** Register */
XMLRequest * requestSignUp( const irr::core::stringw &username, const XMLRequest * requestSignUp( const irr::core::stringw &username,
const irr::core::stringw &password, const irr::core::stringw &password,
const irr::core::stringw &password_ver, const irr::core::stringw &password_ver,
const irr::core::stringw &email, const irr::core::stringw &email,
bool terms); bool terms);
const XMLRequest * requestRecovery(const irr::core::stringw &username,
const irr::core::stringw &email);
/** Returns the username if signed in. */ /** Returns the username if signed in. */
irr::core::stringw getUserName() const; const irr::core::stringw getUserName() const;
bool isSignedIn() const { return m_state == US_SIGNED_IN; } const UserState getUserState() const { return m_state.getAtomic(); }
bool isGuest() const { return m_state == US_GUEST; } const std::string getToken() const { return m_token.getAtomic(); }
bool isSigningIn() const { return m_state == US_SIGNING_IN; }
UserState getUserState() { return m_state; }
std::string getToken() const { return m_token; }
}; // class CurrentUser }; // class CurrentUser

View File

@ -1,6 +1,8 @@
// //
// SuperTuxKart - a fun racing game with go-kart // SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Glenn De Jonghe // Copyright (C) 2010 Lucas Baudin
// 2011 Joerg Henrichs
// 2013 Glenn De Jonghe
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License // modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
// //
// SuperTuxKart - a fun racing game with go-kart // SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Glenn De Jonghe // Copyright (C) 2010 Lucas Baudin
// 2011 Joerg Henrichs
// 2013 Glenn De Jonghe
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License // modify it under the terms of the GNU General Public License

View File

@ -40,6 +40,11 @@ namespace Online
return irr::core::stringw(_("Validating registration info")) + loadingDots(); return irr::core::stringw(_("Validating registration info")) + loadingDots();
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
irr::core::stringw recovery()
{
return irr::core::stringw(_("Validating recovery info")) + loadingDots();
}
// ------------------------------------------------------------------------
irr::core::stringw signedInAs(const irr::core::stringw & name) irr::core::stringw signedInAs(const irr::core::stringw & name)
{ {

View File

@ -30,6 +30,7 @@ namespace Online
irr::core::stringw signingIn (); irr::core::stringw signingIn ();
irr::core::stringw signingOut (); irr::core::stringw signingOut ();
irr::core::stringw signingUp (); irr::core::stringw signingUp ();
irr::core::stringw recovery ();
irr::core::stringw joiningServer (); irr::core::stringw joiningServer ();
irr::core::stringw creatingServer (); irr::core::stringw creatingServer ();
irr::core::stringw fetchingServers (); irr::core::stringw fetchingServers ();

View File

@ -24,6 +24,7 @@
#endif #endif
#include <curl/curl.h> #include <curl/curl.h>
#include <assert.h> #include <assert.h>
@ -46,7 +47,7 @@ namespace Online{
void Request::execute() void Request::execute()
{ {
beforeOperation(); prepareOperation();
operation(); operation();
afterOperation(); afterOperation();
} }
@ -64,13 +65,15 @@ namespace Online{
//Negative numbers are reserved for special requests ment for the HTTP Manager //Negative numbers are reserved for special requests ment for the HTTP Manager
assert(type >= 0); assert(type >= 0);
m_url.setAtomic(""); m_url.setAtomic("");
m_parameters = new Parameters; MutexLocker(m_parameters);
m_parameters.getData() = new Parameters;
m_progress.setAtomic(0); m_progress.setAtomic(0);
} }
HTTPRequest::~HTTPRequest() HTTPRequest::~HTTPRequest()
{ {
delete m_parameters; MutexLocker(m_parameters);
delete m_parameters.getData();
} }
bool HTTPRequest::isAllowedToAdd() bool HTTPRequest::isAllowedToAdd()
@ -83,68 +86,73 @@ namespace Online{
return ok; return ok;
} }
void HTTPRequest::afterOperation() void HTTPRequest::prepareOperation()
{ {
callback(); m_curl_session = curl_easy_init();
Request::afterOperation(); if(!m_curl_session)
{
Log::error("HTTPRequest::prepareOperation", "LibCurl session not initialized.");
return;
}
curl_easy_setopt(m_curl_session, CURLOPT_URL, m_url.getAtomic().c_str());
curl_easy_setopt(m_curl_session, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(m_curl_session, CURLOPT_WRITEFUNCTION, &HTTPRequest::WriteCallback);
curl_easy_setopt(m_curl_session, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(m_curl_session, CURLOPT_PROGRESSDATA, this);
curl_easy_setopt(m_curl_session, CURLOPT_PROGRESSFUNCTION, &HTTPRequest::progressDownload);
curl_easy_setopt(m_curl_session, CURLOPT_CONNECTTIMEOUT, 20);
curl_easy_setopt(m_curl_session, CURLOPT_LOW_SPEED_LIMIT, 10);
curl_easy_setopt(m_curl_session, CURLOPT_LOW_SPEED_TIME, 20);
} }
std::string HTTPRequest::downloadPage() void HTTPRequest::operation()
{ {
CURL * curl_session; if(!m_curl_session)
curl_session = curl_easy_init(); return;
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; Parameters::iterator iter;
std::string postString = ""; std::string postString("");
for (iter = m_parameters->begin(); iter != m_parameters->end(); ++iter) m_parameters.lock();
for (iter = m_parameters.getData()->begin(); iter != m_parameters.getData()->end(); ++iter)
{ {
if(iter != m_parameters->begin()) if(iter != m_parameters.getData()->begin())
postString.append("&"); postString.append("&");
char * escaped = curl_easy_escape(curl_session , iter->first.c_str(), iter->first.size()); char * escaped = curl_easy_escape(m_curl_session , iter->first.c_str(), iter->first.size());
postString.append(escaped); postString.append(escaped);
curl_free(escaped); curl_free(escaped);
postString.append("="); postString.append("=");
escaped = curl_easy_escape(curl_session , iter->second.c_str(), iter->second.size()); escaped = curl_easy_escape(m_curl_session , iter->second.c_str(), iter->second.size());
postString.append(escaped); postString.append(escaped);
curl_free(escaped); curl_free(escaped);
} }
curl_easy_setopt(curl_session, CURLOPT_POSTFIELDS, postString.c_str()); m_parameters.unlock();
std::string readBuffer; curl_easy_setopt(m_curl_session, CURLOPT_POSTFIELDS, postString.c_str());
curl_easy_setopt(curl_session, CURLOPT_WRITEFUNCTION, &HTTPRequest::WriteCallback); std::string uagent( std::string("SuperTuxKart/") + STK_VERSION );
curl_easy_setopt(curl_session, CURLOPT_NOPROGRESS, 0); #ifdef WIN32
curl_easy_setopt(curl_session, CURLOPT_PROGRESSDATA, this); uagent += (std::string)" (Windows)";
curl_easy_setopt(curl_session, CURLOPT_PROGRESSFUNCTION, &HTTPRequest::progressDownload); #elif defined(__APPLE__)
curl_easy_setopt(curl_session, CURLOPT_FILE, &readBuffer); uagent += (std::string)" (Macintosh)";
// Timeout #elif defined(__FreeBSD__)
// Reduce the connection phase timeout (it's 300 by default). uagent += (std::string)" (FreeBSD)";
// Add a low speed limit to have a sort of timeout in the #elif defined(linux)
// download phase. Being under 10 B/s during a certain time will uagent += (std::string)" (Linux)";
// probably only happen when no access to the net is available. #else
// The timeout is set to 20s, it should be enough to not produce // Unknown system type
// false positive error. #endif
curl_easy_setopt(curl_session, CURLOPT_CONNECTTIMEOUT, 20); curl_easy_setopt(m_curl_session, CURLOPT_USERAGENT, uagent.c_str());
curl_easy_setopt(curl_session, CURLOPT_LOW_SPEED_LIMIT, 10);
curl_easy_setopt(curl_session, CURLOPT_LOW_SPEED_TIME, 20); m_curl_code = curl_easy_perform(m_curl_session);
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;
} }
void HTTPRequest::afterOperation()
{
if(m_curl_code == CURLE_OK)
setProgress(1.0f);
else
setProgress(-1.0f);
curl_easy_cleanup(m_curl_session);
callback();
Request::afterOperation();
}
size_t HTTPRequest::WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) size_t HTTPRequest::WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{ {
@ -202,38 +210,68 @@ namespace Online{
XMLRequest::XMLRequest(int type, bool manage_memory, int priority) XMLRequest::XMLRequest(int type, bool manage_memory, int priority)
: HTTPRequest(priority, manage_memory, type) : HTTPRequest(priority, manage_memory, type)
{ {
m_string_buffer = "";
m_info.setAtomic(""); m_info.setAtomic("");
m_success.setAtomic(false); m_success.setAtomic(false);
m_result = NULL; MutexLocker(m_result);
m_result.getData() = NULL;
} }
XMLRequest::~XMLRequest() XMLRequest::~XMLRequest()
{ {
delete m_result; MutexLocker(m_result);
delete m_result.getData();
}
void XMLRequest::prepareOperation()
{
HTTPRequest::prepareOperation();
curl_easy_setopt(m_curl_session, CURLOPT_WRITEDATA, &m_string_buffer);
} }
void XMLRequest::operation() void XMLRequest::operation()
{ {
m_result = file_manager->createXMLTreeFromString(downloadPage()); HTTPRequest::operation();
MutexLocker(m_result);
m_result.getData() = file_manager->createXMLTreeFromString(m_string_buffer);
} }
void XMLRequest::afterOperation() void XMLRequest::afterOperation()
{ {
const XMLNode * xml = this->getResult(); if(m_curl_code != CURLE_OK)
Log::error( "XMLRequest::afterOperation", "curl_easy_perform() failed: %s", curl_easy_strerror(m_curl_code));
else
Log::info( "XMLRequest::afterOperation", "Received : %s", m_string_buffer.c_str());
m_result.lock();;
bool success = false; bool success = false;
irr::core::stringw info; irr::core::stringw info;
std::string rec_success; std::string rec_success;
if(xml->get("success", &rec_success)) if(m_result.getData()->get("success", &rec_success))
{ {
if (rec_success =="yes") if (rec_success =="yes")
success = true; success = true;
xml->get("info", &info); m_result.getData()->get("info", &info);
} }
else else
info = _("Unable to connect to the server. Check your internet connection or try again later."); info = _("Unable to connect to the server. Check your internet connection or try again later.");
m_info.setAtomic(info); m_result.unlock();
m_info.lock();
m_info.getData() = info;
m_info.unlock();
m_success.setAtomic(success); m_success.setAtomic(success);
HTTPRequest::afterOperation(); HTTPRequest::afterOperation();
} }
const XMLNode * XMLRequest::getResult() const
{
MutexLocker(m_result);
return m_result.getData();
}
const irr::core::stringw & XMLRequest::getInfo() const
{
MutexLocker(m_info);
return m_info.getData();
}
} // namespace Online } // namespace Online

View File

@ -1,5 +1,7 @@
// SuperTuxKart - a fun racing game with go-kart // SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Glenn De Jonghe // Copyright (C) 2011 Joerg Henrichs
// 2013 Glenn De Jonghe
//
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License // modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3 // as published by the Free Software Foundation; either version 3
@ -18,12 +20,14 @@
#define HEADER_ONLINE_REQUEST_HPP #define HEADER_ONLINE_REQUEST_HPP
#include <string> #include <string>
#include <curl/curl.h>
#include "utils/cpp2011.h" #include "utils/cpp2011.h"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
#include "utils/synchronised.hpp" #include "utils/synchronised.hpp"
#include "io/file_manager.hpp" #include "io/file_manager.hpp"
namespace Online{ namespace Online{
/** /**
@ -54,8 +58,8 @@ namespace Online{
/** Set to though if the reply of the request is in and callbacks are executed */ /** Set to though if the reply of the request is in and callbacks are executed */
Synchronised<bool> m_done; Synchronised<bool> m_done;
virtual void beforeOperation() {} virtual void prepareOperation() {}
virtual void operation() {}; virtual void operation() {}
virtual void afterOperation(); virtual void afterOperation();
public: public:
@ -115,22 +119,20 @@ namespace Online{
typedef std::map<std::string, std::string> Parameters; typedef std::map<std::string, std::string> Parameters;
/** The progress indicator. 0 untill it is started and the first /** The progress indicator. 0 untill it is started and the first
* packet is downloaded. At the end either -1 (error) or 1 * packet is downloaded. At the end either -1 (error) or 1
* (everything ok) at the end. */ * (everything ok) at the end. */
Synchronised<float> m_progress; Synchronised<float> m_progress;
Synchronised<std::string> m_url; Synchronised<std::string> m_url;
Parameters * m_parameters; Synchronised<Parameters *> m_parameters;
CURL * m_curl_session;
CURLcode m_curl_code;
virtual void prepareOperation() OVERRIDE;
virtual void operation() OVERRIDE;
virtual void afterOperation() OVERRIDE; virtual void afterOperation() OVERRIDE;
/** Executed when a request has finished. */ /** Executed when a request has finished. */
virtual void callback() {} 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, static int progressDownload( void *clientp,
double dltotal, double dltotal,
@ -149,14 +151,17 @@ namespace Online{
virtual ~HTTPRequest(); virtual ~HTTPRequest();
void setParameter(const std::string & name, const std::string &value){ void setParameter(const std::string & name, const std::string &value){
(*m_parameters)[name] = value; MutexLocker(m_parameters);
(*m_parameters.getData())[name] = value;
}; };
void setParameter(const std::string & name, const irr::core::stringw &value){ void setParameter(const std::string & name, const irr::core::stringw &value){
(*m_parameters)[name] = irr::core::stringc(value.c_str()).c_str(); MutexLocker(m_parameters);
(*m_parameters.getData())[name] = irr::core::stringc(value.c_str()).c_str();
} }
template <typename T> template <typename T>
void setParameter(const std::string & name, const T& value){ void setParameter(const std::string & name, const T& value){
(*m_parameters)[name] = StringUtils::toString(value); MutexLocker(m_parameters);
(*m_parameters.getData())[name] = StringUtils::toString(value);
} }
/** Returns the current progress. */ /** Returns the current progress. */
@ -179,27 +184,25 @@ namespace Online{
class XMLRequest : public HTTPRequest class XMLRequest : public HTTPRequest
{ {
protected : private:
Synchronised<XMLNode *> m_result;
std::string m_string_buffer;
XMLNode * m_result; protected :
Synchronised<irr::core::stringw> m_info; Synchronised<irr::core::stringw> m_info;
Synchronised<bool> m_success; Synchronised<bool> m_success;
virtual void operation() OVERRIDE; virtual void prepareOperation() OVERRIDE;
virtual void afterOperation() OVERRIDE; virtual void operation() OVERRIDE;
virtual void afterOperation() OVERRIDE;
public : public :
XMLRequest(int type = 0, bool manage_memory = false, int priority = 1); XMLRequest(int type = 0, bool manage_memory = false, int priority = 1);
virtual ~XMLRequest(); virtual ~XMLRequest();
virtual XMLNode * getResult() const { return m_result; } const XMLNode * getResult() const;
const irr::core::stringw getInfo() { const irr::core::stringw & getInfo() const;
m_info.lock(); bool isSuccess() const { return m_success.getAtomic(); }
const irr::core::stringw info = m_info.getData();
m_info.unlock();
return info;
}
bool isSuccess() const { return m_success.getAtomic(); }
}; };
} //namespace Online } //namespace Online

View File

@ -30,60 +30,49 @@
namespace Online{ namespace Online{
static Synchronised<ServersManager*> manager_singleton(NULL); static ServersManager* manager_singleton(NULL);
ServersManager* ServersManager::acquire() ServersManager* ServersManager::get()
{ {
manager_singleton.lock(); if (manager_singleton == NULL)
ServersManager * manager = manager_singleton.getData(); manager_singleton = new ServersManager();
if (manager == NULL) return manager_singleton;
{
manager_singleton.unlock();
manager = new ServersManager();
manager_singleton.setAtomic(manager);
manager_singleton.lock();
}
return manager;
}
void ServersManager::release()
{
manager_singleton.unlock();
} }
void ServersManager::deallocate() void ServersManager::deallocate()
{ {
manager_singleton.lock(); delete manager_singleton;
ServersManager* manager = manager_singleton.getData(); manager_singleton = NULL;
delete manager;
manager = NULL;
manager_singleton.unlock();
} // deallocate } // deallocate
// ============================================================================ // ============================================================================
ServersManager::ServersManager(){ ServersManager::ServersManager(){
m_info_message = ""; m_last_load_time.setAtomic(0.0f);
m_last_load_time = 0.0f; m_joined_server.setAtomic(NULL);
m_joined_server = NULL;
} }
ServersManager::~ServersManager(){ ServersManager::~ServersManager(){
cleanUpServers(); cleanUpServers();
delete m_joined_server; MutexLocker(m_joined_server);
delete m_joined_server.getData();
} }
// ============================================================================ // ============================================================================
void ServersManager::cleanUpServers() void ServersManager::cleanUpServers()
{ {
m_sorted_servers.clearAndDeleteAll(); m_sorted_servers.lock();
m_mapped_servers.clear(); m_sorted_servers.getData().clearAndDeleteAll();
m_sorted_servers.unlock();
m_mapped_servers.lock();
m_mapped_servers.getData().clear();
m_mapped_servers.unlock();
} }
// ============================================================================ // ============================================================================
ServersManager::RefreshRequest * ServersManager::refreshRequest(bool request_now) ServersManager::RefreshRequest * ServersManager::refreshRequest(bool request_now) const
{ {
RefreshRequest * request = NULL; RefreshRequest * request = NULL;
if(Time::getRealTime() - m_last_load_time > SERVER_REFRESH_INTERVAL) if(Time::getRealTime() - m_last_load_time.getAtomic() > SERVER_REFRESH_INTERVAL)
{ {
request = new RefreshRequest(); request = new RefreshRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php"); request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
@ -104,63 +93,84 @@ namespace Online{
{ {
addServer(new Server(*servers_xml->getNode(i))); addServer(new Server(*servers_xml->getNode(i)));
} }
m_last_load_time = (float)Time::getRealTime(); m_last_load_time.setAtomic((float)Time::getRealTime());
} }
m_info_message = input->getInfo();
//FIXME error message //FIXME error message
} }
void ServersManager::RefreshRequest::callback() void ServersManager::RefreshRequest::callback()
{ {
ServersManager::acquire()->refresh(this); ServersManager::get()->refresh(this);
ServersManager::release();
} }
// ============================================================================ // ============================================================================
Server * ServersManager::getQuickPlay() const Server * ServersManager::getQuickPlay() const
{ {
if(m_sorted_servers.size() > 0) /*if(m_sorted_servers.size() > 0)
return getServerBySort(0); return getServerBySort(0);
*/
return NULL; return NULL;
} }
// ============================================================================ // ============================================================================
void ServersManager::setJoinedServer(uint32_t id) void ServersManager::setJoinedServer(uint32_t id)
{ {
delete m_joined_server; MutexLocker(m_joined_server);
delete m_joined_server.getData();
//It's a copy! //It's a copy!
m_joined_server = new Server(*getServerByID(id)); m_joined_server.getData() = new Server(*getServerByID(id));
} }
// ============================================================================ // ============================================================================
void ServersManager::unsetJoinedServer() void ServersManager::unsetJoinedServer()
{ {
delete m_joined_server; MutexLocker(m_joined_server);
m_joined_server = NULL; delete m_joined_server.getData();
m_joined_server.getData() = NULL;
} }
// ============================================================================ // ============================================================================
void ServersManager::addServer(Server * server) void ServersManager::addServer(Server * server)
{ {
m_sorted_servers.push_back(server); m_sorted_servers.lock();
m_mapped_servers[server->getServerId()] = server; m_sorted_servers.getData().push_back(server);
m_sorted_servers.unlock();
m_mapped_servers.lock();
m_mapped_servers.getData()[server->getServerId()] = server;
m_mapped_servers.unlock();
} }
// ============================================================================ // ============================================================================
int ServersManager::getNumServers () int ServersManager::getNumServers () const
{ {
return m_sorted_servers.size(); MutexLocker(m_sorted_servers);
return m_sorted_servers.getData().size();
} }
// ============================================================================ // ============================================================================
Server * ServersManager::getServerBySort (int index) const Server * ServersManager::getServerBySort (int index) const
{ {
return m_sorted_servers.get(index); MutexLocker(m_sorted_servers);
return m_sorted_servers.getData().get(index);
} }
// ============================================================================ // ============================================================================
Server * ServersManager::getServerByID (uint32_t id) const Server * ServersManager::getServerByID (uint32_t id) const
{ {
return m_mapped_servers[id]; MutexLocker(m_mapped_servers);
return m_mapped_servers.getData().at(id);
} }
// ============================================================================
Server * ServersManager::getJoinedServer() const
{
return m_joined_server.getAtomic();
}
// ============================================================================
void ServersManager::sort(bool sort_desc){
MutexLocker(m_sorted_servers);
m_sorted_servers.getData().insertionSort(0, sort_desc);
}
} // namespace Online } // namespace Online

View File

@ -23,6 +23,8 @@
#include "utils/types.hpp" #include "utils/types.hpp"
#include "online/server.hpp" #include "online/server.hpp"
#include "http_manager.hpp" #include "http_manager.hpp"
#include "utils/synchronised.hpp"
@ -51,35 +53,32 @@ namespace Online {
ServersManager(); ServersManager();
~ServersManager(); ~ServersManager();
/** Sorted vector of servers */ /** Sorted vector of servers */
PtrVector<Server> m_sorted_servers; Synchronised<PtrVector<Server> > m_sorted_servers;
/** Maps server id's to the same servers*/ /** Maps server id's to the same servers*/
std::map<uint32_t, Server*> m_mapped_servers; Synchronised<std::map<uint32_t, Server*> > m_mapped_servers;
/** This is a pointer to a copy of the server, the moment it got joined */ /** This is a pointer to a copy of the server, the moment it got joined */
Server * m_joined_server; Synchronised<Server *> m_joined_server;
bool m_not_fetched; Synchronised<float> m_last_load_time;
irr::core::stringw m_info_message; void refresh(RefreshRequest * input);
float m_last_load_time; void cleanUpServers();
void refresh(RefreshRequest * input);
void cleanUpServers();
public: public:
// Singleton // Singleton
static ServersManager* acquire(); static ServersManager* get();
static void release(); static void deallocate();
static void deallocate();
RefreshRequest * refreshRequest(bool request_now = true); RefreshRequest * refreshRequest(bool request_now = true) const;
void setJoinedServer(uint32_t server_id); void setJoinedServer(uint32_t server_id);
void unsetJoinedServer(); void unsetJoinedServer();
void addServer(Server * server); void addServer(Server * server);
int getNumServers (); int getNumServers () const;
Server * getServerByID (uint32_t server_id); const Server * getServerByID (uint32_t server_id) const;
Server * getServerBySort (int index); const Server * getServerBySort (int index) const;
void sort(bool sort_desc) { m_sorted_servers.insertionSort(0, sort_desc); } void sort(bool sort_desc);
Server * getJoinedServer() { return m_joined_server; } Server * getJoinedServer() const;
//Returns the best server to join //Returns the best server to join
Server * getQuickPlay(); const Server * getQuickPlay() const;
}; // class ServersManager }; // class ServersManager

View File

@ -22,15 +22,21 @@
#include <sstream> #include <sstream>
#include <stdlib.h> #include <stdlib.h>
using namespace Online;
namespace Online{ namespace Online{
// ============================================================================ // ============================================================================
User::User(const irr::core::stringw &username) User::User ( const irr::core::stringw & username,
const uint32_t & userid
)
{ {
m_name = username; setUserName(username);
setUserID(userid);
} }
// ============================================================================ // ============================================================================
User::User(uint32_t id) User::User(uint32_t id)
{ {
m_id = id; setUserName("");
setUserID(id);
} }
} // namespace Online } // namespace Online

View File

@ -32,22 +32,24 @@ namespace Online{
class User class User
{ {
private: private:
Synchronised<irr::core::stringw> m_name;
Synchronised<uint32_t> m_id;
protected: protected:
irr::core::stringw m_name; void setUserName (const irr::core::stringw & name) { m_name.setAtomic(name); }
uint32_t m_id; void setUserID (const uint32_t & id) { m_id.setAtomic(id); }
User(){}
public: public:
User( const irr::core::stringw & username,
const uint32_t & userid
);
virtual ~User() {};
User(const irr::core::stringw &username); virtual const irr::core::stringw getUserName() const { return m_name.getAtomic(); }
const uint32_t getUserID() const { return m_id.getAtomic(); }
User(uint32_t id); User(uint32_t id);
irr::core::stringw getUserName() const { return m_name; }
uint32_t getUserID() const { return m_id; }
}; // class User }; // class User
} // namespace Online } // namespace Online
#endif #endif

View File

@ -214,7 +214,7 @@ void AddonsScreen::loadList()
// Get the filter by rating. // Get the filter by rating.
GUIEngine::SpinnerWidget* w_filter_rating = GUIEngine::SpinnerWidget* w_filter_rating =
getWidget<GUIEngine::SpinnerWidget>("filter_rating"); getWidget<GUIEngine::SpinnerWidget>("filter_rating");
float rating = 1.0 + w_filter_rating->getValue() / 2.0; float rating = 1.0f + w_filter_rating->getValue() / 2.0f;
// First create a list of sorted entries // First create a list of sorted entries
PtrVector<const Addon, REF> sorted_list; PtrVector<const Addon, REF> sorted_list;

View File

@ -56,8 +56,7 @@ void CreateServerScreen::loadedFromFile()
m_name_widget = getWidget<TextBoxWidget>("name"); m_name_widget = getWidget<TextBoxWidget>("name");
assert(m_name_widget != NULL); assert(m_name_widget != NULL);
m_name_widget->setText(CurrentUser::acquire()->getUserName() + _("'s server")); m_name_widget->setText(CurrentUser::get()->getUserName() + _("'s server"));
CurrentUser::release();
m_max_players_widget = getWidget<SpinnerWidget>("max_players"); m_max_players_widget = getWidget<SpinnerWidget>("max_players");
assert(m_max_players_widget != NULL); assert(m_max_players_widget != NULL);
m_max_players_widget->setValue(8); m_max_players_widget->setValue(8);
@ -137,8 +136,7 @@ void CreateServerScreen::serverCreationRequest()
else else
{ {
//m_options_widget->setDeactivated(); //m_options_widget->setDeactivated();
m_server_creation_request = Online::CurrentUser::acquire()->requestServerCreation(name, max_players); m_server_creation_request = Online::CurrentUser::get()->requestServerCreation(name, max_players);
Online::CurrentUser::release();
return; return;
} }
sfx_manager->quickSound("anvil"); sfx_manager->quickSound("anvil");

View File

@ -46,7 +46,7 @@ private:
GUIEngine::IconButtonWidget * m_create_widget; GUIEngine::IconButtonWidget * m_create_widget;
GUIEngine::IconButtonWidget * m_cancel_widget; GUIEngine::IconButtonWidget * m_cancel_widget;
Online::CurrentUser::ServerCreationRequest * m_server_creation_request; const Online::CurrentUser::ServerCreationRequest * m_server_creation_request;
/** \brief Sets which widget has to be focused. Depends on the user state. */ /** \brief Sets which widget has to be focused. Depends on the user state. */
void setInitialFocus(); void setInitialFocus();

View File

@ -26,6 +26,7 @@
#include "utils/translation.hpp" #include "utils/translation.hpp"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
#include "states_screens/dialogs/registration_dialog.hpp" #include "states_screens/dialogs/registration_dialog.hpp"
#include "states_screens/dialogs/recovery_dialog.hpp"
#include "online/messages.hpp" #include "online/messages.hpp"
@ -41,6 +42,7 @@ LoginDialog::LoginDialog(const Message message_type) :
{ {
m_self_destroy = false; m_self_destroy = false;
m_open_registration_dialog = false; m_open_registration_dialog = false;
m_open_recovery_dialog = false;
m_sign_in_request = NULL; m_sign_in_request = NULL;
loadFromFile("online/login_dialog.stkgui"); loadFromFile("online/login_dialog.stkgui");
@ -86,6 +88,7 @@ LoginDialog::LoginDialog(const Message message_type) :
assert(m_register_widget != NULL); assert(m_register_widget != NULL);
m_as_guest_widget = getWidget<IconButtonWidget>("as_guest"); m_as_guest_widget = getWidget<IconButtonWidget>("as_guest");
assert(m_as_guest_widget != NULL); assert(m_as_guest_widget != NULL);
m_as_guest_widget->setDeactivated();
m_cancel_widget = getWidget<IconButtonWidget>("cancel"); m_cancel_widget = getWidget<IconButtonWidget>("cancel");
assert(m_cancel_widget != NULL); assert(m_cancel_widget != NULL);
@ -115,8 +118,7 @@ void LoginDialog::login()
else else
{ {
m_options_widget->setDeactivated(); m_options_widget->setDeactivated();
m_sign_in_request = Online::CurrentUser::acquire()->requestSignIn(username,password, m_remember_widget->getState()); m_sign_in_request = Online::CurrentUser::get()->requestSignIn(username,password, m_remember_widget->getState());
Online::CurrentUser::release();
} }
} }
@ -142,6 +144,11 @@ GUIEngine::EventPropagation LoginDialog::processEvent(const std::string& eventSo
m_open_registration_dialog = true; m_open_registration_dialog = true;
return GUIEngine::EVENT_BLOCK; return GUIEngine::EVENT_BLOCK;
} }
else if(selection == m_recovery_widget->m_properties[PROP_ID])
{
m_open_recovery_dialog = true;
return GUIEngine::EVENT_BLOCK;
}
} }
return GUIEngine::EVENT_LET; return GUIEngine::EVENT_LET;
} }
@ -192,8 +199,8 @@ void LoginDialog::onUpdate(float dt)
m_info_widget->setText(Online::Messages::signingIn(), false); m_info_widget->setText(Online::Messages::signingIn(), false);
} }
} }
//If we want to open the registration dialog, we need to close this one first //If we want to open another dialog, we need to close this one first
m_open_registration_dialog && (m_self_destroy = true); (m_open_registration_dialog || m_open_recovery_dialog) && (m_self_destroy = true);
// It's unsafe to delete from inside the event handler so we do it here // It's unsafe to delete from inside the event handler so we do it here
if (m_self_destroy) if (m_self_destroy)
@ -201,6 +208,8 @@ void LoginDialog::onUpdate(float dt)
ModalDialog::dismiss(); ModalDialog::dismiss();
if (m_open_registration_dialog) if (m_open_registration_dialog)
new RegistrationDialog(); new RegistrationDialog();
else if (m_open_recovery_dialog)
new RecoveryDialog();
return; return;
} }
} }

View File

@ -37,7 +37,8 @@ private:
bool m_self_destroy; bool m_self_destroy;
bool m_open_registration_dialog; bool m_open_registration_dialog;
Online::CurrentUser::SignInRequest * m_sign_in_request; bool m_open_recovery_dialog;
const Online::CurrentUser::SignInRequest * m_sign_in_request;
GUIEngine::LabelWidget * m_message_widget; GUIEngine::LabelWidget * m_message_widget;
GUIEngine::TextBoxWidget * m_username_widget; GUIEngine::TextBoxWidget * m_username_widget;
GUIEngine::TextBoxWidget * m_password_widget; GUIEngine::TextBoxWidget * m_password_widget;

View File

@ -0,0 +1,190 @@
// 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/recovery_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/messages.hpp"
using namespace GUIEngine;
using namespace irr;
using namespace irr::gui;
using namespace Online;
// -----------------------------------------------------------------------------
RecoveryDialog::RecoveryDialog() :
ModalDialog(0.8f,0.8f)
{
m_recovery_request = NULL;
m_self_destroy = false;
m_show_recovery_input = true;
}
// -----------------------------------------------------------------------------
RecoveryDialog::~RecoveryDialog()
{
delete m_recovery_request;
}
// -----------------------------------------------------------------------------
void RecoveryDialog::showRecoveryInput(){
m_show_recovery_input = false;
clearWindow();
m_phase = Input;
loadFromFile("online/recovery_input.stkgui");
m_username_widget = getWidget<TextBoxWidget>("username");
assert(m_username_widget != NULL);
m_username_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
m_email_widget = getWidget<TextBoxWidget>("email");
assert(m_email_widget != NULL);
m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL);
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL);
m_submit_widget = getWidget<IconButtonWidget>("submit");
assert(m_submit_widget != NULL);
m_cancel_widget = getWidget<IconButtonWidget>("cancel");
assert(m_cancel_widget != NULL);
}
// -----------------------------------------------------------------------------
void RecoveryDialog::showRecoveryInfo(){
m_show_recovery_info = false;
clearWindow();
m_phase = Info;
loadFromFile("online/recovery_info.stkgui");
m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL);
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL);
m_cancel_widget = getWidget<IconButtonWidget>("cancel");
assert(m_cancel_widget != NULL);
}
// -----------------------------------------------------------------------------
bool RecoveryDialog::onEscapePressed()
{
return m_cancel_widget->isActivated();
}
// -----------------------------------------------------------------------------
void RecoveryDialog::processInput()
{
const stringw username = m_username_widget->getText().trim();
const stringw email = m_email_widget->getText().trim();
if (username.size() < 4 || username.size() > 30 || email.size() < 4 || email.size() > 50)
{
sfx_manager->quickSound("anvil");
m_info_widget->setErrorColor();
m_info_widget->setText(_("Username and/or email address invalid."), false);
}
else
{
m_info_widget->setDefaultColor();
m_options_widget->setDeactivated();
m_recovery_request = CurrentUser::get()->requestRecovery(username, email);
}
}
// -----------------------------------------------------------------------------
GUIEngine::EventPropagation RecoveryDialog::processEvent(const std::string& eventSource)
{
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 (selection == m_submit_widget->m_properties[PROP_ID])
{
processInput();
return GUIEngine::EVENT_BLOCK;
}
return GUIEngine::EVENT_LET;
}
// -----------------------------------------------------------------------------
void RecoveryDialog::onEnterPressedInternal()
{
if (GUIEngine::isFocusedForPlayer(m_options_widget, PLAYER_ID_GAME_MASTER))
return;
if (m_submit_widget->isActivated())
processInput();
}
// -----------------------------------------------------------------------------
void RecoveryDialog::onUpdate(float dt)
{
if(m_recovery_request != NULL)
{
if(m_recovery_request->isDone())
{
if(m_recovery_request->isSuccess())
{
m_show_recovery_info = true;
}
else
{
sfx_manager->quickSound( "anvil" );
m_info_widget->setErrorColor();
m_info_widget->setText(m_recovery_request->getInfo(), false);
m_options_widget->setActivated();
}
delete m_recovery_request;
m_recovery_request = NULL;
}
else
{
m_info_widget->setText(Messages::recovery(), false);
}
}
// It's unsafe to delete from inside the event handler so we do it here
if (m_self_destroy)
ModalDialog::dismiss();
else if (m_show_recovery_input)
showRecoveryInput();
else if (m_show_recovery_info)
showRecoveryInfo();
}

View File

@ -0,0 +1,71 @@
// 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_RECOVERY_DIALOG_HPP
#define HEADER_RECOVERY_DIALOG_HPP
#include <irrString.h>
#include "guiengine/modaldialog.hpp"
#include "guiengine/widgets.hpp"
#include "online/current_user.hpp"
/**
* \brief Dialog that allows a user to recover his account
* \ingroup states_screens
*/
class RecoveryDialog : public GUIEngine::ModalDialog
{
public:
enum Phase
{
Input = 1,
Info = 2,
};
RecoveryDialog();
~RecoveryDialog();
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_recovery_input;
bool m_show_recovery_info;
const Online::XMLRequest * m_recovery_request;
GUIEngine::TextBoxWidget * m_username_widget;
GUIEngine::TextBoxWidget * m_email_widget;
GUIEngine::LabelWidget * m_info_widget;
GUIEngine::RibbonWidget * m_options_widget;
GUIEngine::IconButtonWidget * m_submit_widget;
GUIEngine::IconButtonWidget * m_cancel_widget;
void showRecoveryInput();
void showRecoveryInfo();
void processInput();
};
#endif

View File

@ -35,26 +35,20 @@ using namespace Online;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
RegistrationDialog::RegistrationDialog(const Phase phase) : RegistrationDialog::RegistrationDialog() :
ModalDialog(0.8f,0.9f) ModalDialog(0.8f,0.9f)
{ {
m_sign_up_request = NULL; m_sign_up_request = NULL;
m_activation_request = NULL;
m_self_destroy = false; m_self_destroy = false;
m_show_registration_info = false; m_show_registration_input = true;
m_show_registration_terms = false; m_show_registration_terms = false;
m_show_registration_activation = false; m_show_registration_info = false;
m_username = ""; m_username = "";
m_email = ""; m_email = "";
m_email_confirm = ""; m_email_confirm = "";
m_password = ""; m_password = "";
m_password_confirm = ""; m_password_confirm = "";
m_agreement = false; m_agreement = false;
//If not asked for the Activation phase, default to the Info phase.
if (phase == Activation)
m_show_registration_activation = true;
else
m_show_registration_info = true;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -62,16 +56,16 @@ RegistrationDialog::RegistrationDialog(const Phase phase) :
RegistrationDialog::~RegistrationDialog() RegistrationDialog::~RegistrationDialog()
{ {
delete m_sign_up_request; delete m_sign_up_request;
delete m_activation_request;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void RegistrationDialog::showRegistrationInfo(){ void RegistrationDialog::showRegistrationInput()
m_show_registration_info = false; {
m_show_registration_input = false;
clearWindow(); clearWindow();
m_phase = Info; m_phase = Input;
loadFromFile("online/registration_info.stkgui"); loadFromFile("online/registration_input.stkgui");
//Password should always be reentered if previous has been clicked, or an error occurred. //Password should always be reentered if previous has been clicked, or an error occurred.
m_password = ""; m_password = "";
@ -113,7 +107,8 @@ void RegistrationDialog::showRegistrationInfo(){
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void RegistrationDialog::showRegistrationTerms(){ void RegistrationDialog::showRegistrationTerms()
{
m_show_registration_terms = false; m_show_registration_terms = false;
clearWindow(); clearWindow();
m_phase = Terms; m_phase = Terms;
@ -139,64 +134,71 @@ void RegistrationDialog::showRegistrationTerms(){
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void RegistrationDialog::showRegistrationActivation(){ void RegistrationDialog::showRegistrationInfo()
m_show_registration_activation = false; {
m_show_registration_info = false;
clearWindow(); clearWindow();
m_phase = Activation; m_phase = Info;
loadFromFile("online/registration_activation.stkgui"); loadFromFile("online/registration_info.stkgui");
m_info_widget = getWidget<LabelWidget>("info"); m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL); assert(m_info_widget != NULL);
m_info_widget->setText(m_registration_error, false);
m_options_widget = getWidget<RibbonWidget>("options"); m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL); assert(m_options_widget != NULL);
m_next_widget = getWidget<IconButtonWidget>("next");
assert(m_next_widget != NULL);
m_cancel_widget = getWidget<IconButtonWidget>("cancel"); m_cancel_widget = getWidget<IconButtonWidget>("cancel");
assert(m_cancel_widget != NULL); assert(m_cancel_widget != NULL);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool RegistrationDialog::processInfoEvent(const std::string& eventSource){ void RegistrationDialog::processInput()
if (m_phase == Info) {
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)
{
m_info_widget->setText(_("Passwords don't match!"), false);
}
else if (m_email != m_email_confirm)
{
m_info_widget->setText(_("Emails don't match!"), false);
}
else if (m_username.size() < 4 || m_username.size() > 30)
{
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)
{
m_info_widget->setText(_("Password has to be between 8 and 30 characters long!"), false);
}
else if (m_email.size() < 4 || m_email.size() > 50)
{
m_info_widget->setText(_("Email has to be between 4 and 50 characters long!"), false);
}
else
{
m_show_registration_terms = true;
return;
}
sfx_manager->quickSound( "anvil" );
}
// -----------------------------------------------------------------------------
bool RegistrationDialog::processInputEvent(const std::string& eventSource)
{
if (m_phase == Input)
{ {
if (eventSource == m_next_widget->m_properties[PROP_ID]) if (eventSource == m_next_widget->m_properties[PROP_ID])
{ {
m_username = m_username_widget->getText().trim(); processInput();
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)
{
m_info_widget->setText(_("Passwords don't match!"), false);
}
else if (m_email != m_email_confirm)
{
m_info_widget->setText(_("Emails don't match!"), false);
}
else if (m_username.size() < 4 || m_username.size() > 30)
{
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)
{
m_info_widget->setText(_("Password has to be between 8 and 30 characters long!"), false);
}
else if (m_email.size() < 4 || m_email.size() > 50)
{
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; return true;
} }
} }
@ -205,7 +207,8 @@ bool RegistrationDialog::processInfoEvent(const std::string& eventSource){
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool RegistrationDialog::processTermsEvent(const std::string& eventSource){ bool RegistrationDialog::processTermsEvent(const std::string& eventSource)
{
if (m_phase == Terms) if (m_phase == Terms)
{ {
if (eventSource == m_next_widget->m_properties[PROP_ID]) if (eventSource == m_next_widget->m_properties[PROP_ID])
@ -214,8 +217,7 @@ bool RegistrationDialog::processTermsEvent(const std::string& eventSource){
m_options_widget->setDeactivated(); m_options_widget->setDeactivated();
m_info_widget->setDefaultColor(); m_info_widget->setDefaultColor();
m_info_widget->setText(Messages::signingUp(), false); m_info_widget->setText(Messages::signingUp(), false);
m_sign_up_request = CurrentUser::acquire()->requestSignUp(m_username, m_password, m_password_confirm, m_email, true); m_sign_up_request = CurrentUser::get()->requestSignUp(m_username, m_password, m_password_confirm, m_email, true);
CurrentUser::release();
return true; return true;
} }
else if (eventSource == m_accept_terms_widget->m_properties[PROP_ID]) else if (eventSource == m_accept_terms_widget->m_properties[PROP_ID])
@ -239,16 +241,8 @@ bool RegistrationDialog::processTermsEvent(const std::string& eventSource){
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool RegistrationDialog::processActivationEvent(const std::string& eventSource){ bool RegistrationDialog::processInfoEvent(const std::string& eventSource)
if (m_phase == Activation) {
{
if (eventSource == m_next_widget->m_properties[PROP_ID])
{
//FIXME : activate
m_self_destroy = true;
return true;
}
}
return false; return false;
} }
@ -273,7 +267,7 @@ GUIEngine::EventPropagation RegistrationDialog::processEvent(const std::string&
m_self_destroy = true; m_self_destroy = true;
return GUIEngine::EVENT_BLOCK; return GUIEngine::EVENT_BLOCK;
} }
else if (processInfoEvent(selection) || processTermsEvent(selection) || processActivationEvent(selection)) else if (processInputEvent(selection) || processTermsEvent(selection) || processInfoEvent(selection))
{ {
return GUIEngine::EVENT_BLOCK; return GUIEngine::EVENT_BLOCK;
} }
@ -288,7 +282,7 @@ void RegistrationDialog::onEnterPressedInternal()
if (GUIEngine::isFocusedForPlayer(m_options_widget, PLAYER_ID_GAME_MASTER)) if (GUIEngine::isFocusedForPlayer(m_options_widget, PLAYER_ID_GAME_MASTER))
return; return;
if (m_next_widget->isActivated()) if (m_next_widget->isActivated())
processEvent("next"); processInput();
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -303,12 +297,12 @@ void RegistrationDialog::onUpdate(float dt)
{ {
if(m_sign_up_request->isSuccess()) if(m_sign_up_request->isSuccess())
{ {
m_show_registration_activation = true; m_show_registration_info = true;
} }
else else
{ {
sfx_manager->quickSound( "anvil" ); sfx_manager->quickSound( "anvil" );
m_show_registration_info = true; m_show_registration_input = true;
m_registration_error = m_sign_up_request->getInfo(); m_registration_error = m_sign_up_request->getInfo();
} }
delete m_sign_up_request; delete m_sign_up_request;
@ -322,34 +316,13 @@ void RegistrationDialog::onUpdate(float dt)
} }
} }
} }
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 // It's unsafe to delete from inside the event handler so we do it here
if (m_self_destroy) if (m_self_destroy)
ModalDialog::dismiss(); ModalDialog::dismiss();
else if (m_show_registration_info) else if (m_show_registration_input)
showRegistrationInfo(); showRegistrationInput();
else if (m_show_registration_terms) else if (m_show_registration_terms)
showRegistrationTerms(); showRegistrationTerms();
else if (m_show_registration_activation) else if (m_show_registration_info)
showRegistrationActivation(); showRegistrationInfo();
} }

View File

@ -31,15 +31,13 @@
class RegistrationDialog : public GUIEngine::ModalDialog class RegistrationDialog : public GUIEngine::ModalDialog
{ {
public: public:
enum Phase enum Phase
{ {
Info = 1, Input = 1,
Terms = 2, Terms = 2,
Activation = 4 Info = 4
}; };
RegistrationDialog();
RegistrationDialog(const Phase phase = Info);
~RegistrationDialog(); ~RegistrationDialog();
void onEnterPressedInternal(); void onEnterPressedInternal();
@ -49,15 +47,13 @@ public:
virtual bool onEscapePressed(); virtual bool onEscapePressed();
private: private:
Phase m_phase; Phase m_phase;
bool m_self_destroy; bool m_self_destroy;
bool m_show_registration_info; bool m_show_registration_input;
bool m_show_registration_terms; bool m_show_registration_terms;
bool m_show_registration_activation; bool m_show_registration_info;
Online::XMLRequest * m_sign_up_request; const Online::XMLRequest * m_sign_up_request;
Online::XMLRequest * m_activation_request;
//Saved user input : //Saved user input :
irr::core::stringw m_username; irr::core::stringw m_username;
@ -83,12 +79,13 @@ private:
GUIEngine::CheckBoxWidget * m_accept_terms_widget; GUIEngine::CheckBoxWidget * m_accept_terms_widget;
void showRegistrationInfo(); void showRegistrationInput();
void showRegistrationTerms(); void showRegistrationTerms();
void showRegistrationActivation(); void showRegistrationInfo();
bool processInfoEvent(const std::string& eventSource); void processInput();
bool processInputEvent(const std::string& eventSource);
bool processTermsEvent(const std::string& eventSource); bool processTermsEvent(const std::string& eventSource);
bool processActivationEvent(const std::string& eventSource); bool processInfoEvent(const std::string& eventSource);
}; };

View File

@ -42,11 +42,9 @@ using namespace Online;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
ServerInfoDialog::ServerInfoDialog(uint32_t server_id, uint32_t host_id,bool from_server_creation) : ServerInfoDialog::ServerInfoDialog(uint32_t server_id, uint32_t host_id, bool from_server_creation)
ModalDialog(0.8f,0.8f) : ModalDialog(0.8f,0.8f), m_server_id(server_id), m_host_id(host_id)
{ {
m_server_id = server_id;
m_host_id = host_id;
Log::info("ServerInfoDialog", "Server id is %d, Host id is %d", server_id, host_id); Log::info("ServerInfoDialog", "Server id is %d, Host id is %d", server_id, host_id);
m_self_destroy = false; m_self_destroy = false;
m_enter_lobby = false; m_enter_lobby = false;
@ -57,9 +55,8 @@ ServerInfoDialog::ServerInfoDialog(uint32_t server_id, uint32_t host_id,bool fro
m_name_widget = getWidget<LabelWidget>("name"); m_name_widget = getWidget<LabelWidget>("name");
assert(m_name_widget != NULL); assert(m_name_widget != NULL);
Server * server = ServersManager::acquire()->getServerByID(m_server_id); const Server * server = ServersManager::get()->getServerByID(m_server_id);
m_name_widget->setText(server->getName(),false); m_name_widget->setText(server->getName(),false);
ServersManager::release();
m_info_widget = getWidget<LabelWidget>("info"); m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL); assert(m_info_widget != NULL);
if (m_from_server_creation) if (m_from_server_creation)
@ -84,9 +81,8 @@ ServerInfoDialog::~ServerInfoDialog()
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void ServerInfoDialog::requestJoin() void ServerInfoDialog::requestJoin()
{ {
//m_server_join_request = Online::CurrentUser::acquire()->requestServerJoin(m_server_id); //m_server_join_request = Online::CurrentUser::get()->requestServerJoin(m_server_id);
Online::ServersManager::acquire()->setJoinedServer(m_server_id); Online::ServersManager::get()->setJoinedServer(m_server_id);
Online::ServersManager::release();
ProtocolManager::getInstance()->requestStart(new ConnectToServer(m_server_id, m_host_id)); ProtocolManager::getInstance()->requestStart(new ConnectToServer(m_server_id, m_host_id));
ModalDialog::dismiss(); ModalDialog::dismiss();
StateManager::get()->pushScreen(NetworkingLobby::getInstance()); StateManager::get()->pushScreen(NetworkingLobby::getInstance());

View File

@ -42,11 +42,11 @@ private:
bool m_self_destroy; bool m_self_destroy;
bool m_enter_lobby; bool m_enter_lobby;
bool m_from_server_creation; bool m_from_server_creation;
Online::CurrentUser::ServerJoinRequest * m_server_join_request; const Online::CurrentUser::ServerJoinRequest * m_server_join_request;
float m_load_timer; float m_load_timer;
uint32_t m_server_id; const uint32_t m_server_id;
uint32_t m_host_id; uint32_t m_host_id;
GUIEngine::LabelWidget * m_name_widget; GUIEngine::LabelWidget * m_name_widget;

View File

@ -21,6 +21,7 @@
#include "guiengine/screen.hpp" #include "guiengine/screen.hpp"
#include "guiengine/widgets/button_widget.hpp" #include "guiengine/widgets/button_widget.hpp"
#include "guiengine/widgets/label_widget.hpp" #include "guiengine/widgets/label_widget.hpp"
#include "karts/abstract_kart.hpp"
#include "modes/world.hpp" #include "modes/world.hpp"
#include "states_screens/state_manager.hpp" #include "states_screens/state_manager.hpp"
#include "utils/translation.hpp" #include "utils/translation.hpp"
@ -48,6 +49,8 @@ TutorialMessageDialog::TutorialMessageDialog(irr::core::stringw msg, bool stopGa
ButtonWidget* cancelbtn = getWidget<ButtonWidget>("continue"); ButtonWidget* cancelbtn = getWidget<ButtonWidget>("continue");
cancelbtn->setFocusForPlayer(PLAYER_ID_GAME_MASTER); cancelbtn->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
World::getWorld()->getKart(0)->getControls().reset();
} }
// ------------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------------

View File

@ -86,8 +86,7 @@ void NetworkingLobby::init()
Screen::init(); Screen::init();
setInitialFocus(); setInitialFocus();
DemoWorld::resetIdleTime(); //FIXME : what's this? DemoWorld::resetIdleTime(); //FIXME : what's this?
m_server = ServersManager::acquire()->getJoinedServer(); m_server = ServersManager::get()->getJoinedServer();
ServersManager::release();
m_server_name_widget->setText(m_server->getName(),false); m_server_name_widget->setText(m_server->getName(),false);
} // init } // init

View File

@ -60,8 +60,8 @@ void NetworkingLobbySettings::loadedFromFile()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool NetworkingLobbySettings::hasLostConnection() bool NetworkingLobbySettings::hasLostConnection()
{ {
bool return_value = !Online::CurrentUser::acquire()->isSignedIn(); bool return_value = ( Online::CurrentUser::get()->getUserState() !=
Online::CurrentUser::release(); Online::CurrentUser::US_SIGNED_IN);
return return_value; return return_value;
} }

View File

@ -56,10 +56,9 @@ DEFINE_SCREEN_SINGLETON( OnlineScreen );
OnlineScreen::OnlineScreen() : Screen("online/main.stkgui") OnlineScreen::OnlineScreen() : Screen("online/main.stkgui")
{ {
m_recorded_state = CurrentUser::US_SIGNED_OUT; m_recorded_state = CurrentUser::US_SIGNED_OUT;
CurrentUser::SignInRequest * request = CurrentUser::acquire()->requestSavedSession(); const CurrentUser::SignInRequest * request = CurrentUser::get()->requestSavedSession();
if(request != NULL) if(request != NULL)
m_requests.push_back(request); m_requests.push_back(request);
CurrentUser::release();
} // OnlineScreen } // OnlineScreen
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -101,8 +100,7 @@ void OnlineScreen::loadedFromFile()
bool OnlineScreen::hasStateChanged() bool OnlineScreen::hasStateChanged()
{ {
CurrentUser::UserState previous_state = m_recorded_state; CurrentUser::UserState previous_state = m_recorded_state;
m_recorded_state = CurrentUser::acquire()->getUserState(); m_recorded_state = CurrentUser::get()->getUserState();
CurrentUser::release();
if (previous_state != m_recorded_state) if (previous_state != m_recorded_state)
return true; return true;
return false; return false;
@ -149,8 +147,7 @@ void OnlineScreen::init()
Screen::init(); Screen::init();
setInitialFocus(); setInitialFocus();
DemoWorld::resetIdleTime(); DemoWorld::resetIdleTime();
m_online_status_widget->setText(Messages::signedInAs(CurrentUser::acquire()->getUserName()), false); m_online_status_widget->setText(Messages::signedInAs(CurrentUser::get()->getUserName()), false);
CurrentUser::release();
} // init } // init
@ -211,8 +208,7 @@ void OnlineScreen::eventCallback(Widget* widget, const std::string& name, const
} }
else if (selection == "sign_out") else if (selection == "sign_out")
{ {
CurrentUser::acquire()->requestSignOut(); CurrentUser::get()->requestSignOut();
CurrentUser::release();
} }
else if (selection == "register") else if (selection == "register")
{ {
@ -230,16 +226,13 @@ void OnlineScreen::eventCallback(Widget* widget, const std::string& name, const
{ {
//FIXME temporary and the request join + join sequence should be placed in one method somewhere //FIXME temporary and the request join + join sequence should be placed in one method somewhere
// refresh server list // refresh server list
Online::ServersManager::RefreshRequest* request = ServersManager::acquire()->refreshRequest(false); Online::ServersManager::RefreshRequest* request = ServersManager::get()->refreshRequest(false);
ServersManager::release();
Online::HTTPManager::get()->synchronousRequest(request); Online::HTTPManager::get()->synchronousRequest(request);
delete request; delete request;
// select first one // select first one
Server * server = ServersManager::acquire()->getQuickPlay(); const Server * server = ServersManager::get()->getQuickPlay();
ServersManager::release();
Online::CurrentUser::ServerJoinRequest* request2 = Online::CurrentUser::acquire()->requestServerJoin( server->getServerId(), false); Online::CurrentUser::ServerJoinRequest* request2 = Online::CurrentUser::get()->requestServerJoin( server->getServerId(), false);
Online::CurrentUser::release();
if (request2) if (request2)
{ {
Online::HTTPManager::get()->synchronousRequest(request2); Online::HTTPManager::get()->synchronousRequest(request2);

View File

@ -54,7 +54,7 @@ private:
Online::CurrentUser::UserState m_recorded_state; Online::CurrentUser::UserState m_recorded_state;
PtrVector<Online::XMLRequest> m_requests; PtrVector<const Online::XMLRequest> m_requests;
/** \brief Checks if the recorded state differs from the actual state and sets it. */ /** \brief Checks if the recorded state differs from the actual state and sets it. */
bool hasStateChanged(); bool hasStateChanged();

View File

@ -526,7 +526,7 @@ void RaceGUI::drawEnergyMeter(int x, int y, const AbstractKart *kart,
video::SMaterial m; video::SMaterial m;
if(kart->getControls().m_nitro) if(kart->getControls().m_nitro || kart->isOnMinNitroTime())
m.setTexture(0, m_gauge_full_bright); m.setTexture(0, m_gauge_full_bright);
else else
m.setTexture(0, m_gauge_full); m.setTexture(0, m_gauge_full);

View File

@ -77,44 +77,12 @@ void RaceSetupScreen::eventCallback(Widget* widget, const std::string& name, con
{ {
if (name == "difficulty") if (name == "difficulty")
{ {
RibbonWidget* w = dynamic_cast<RibbonWidget*>(widget); assignDifficulty();
assert(w != NULL);
const std::string& selection = w->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == "novice")
{
UserConfigParams::m_difficulty = RaceManager::DIFFICULTY_EASY;
race_manager->setDifficulty(RaceManager::DIFFICULTY_EASY);
}
else if (selection == "intermediate")
{
UserConfigParams::m_difficulty = RaceManager::DIFFICULTY_MEDIUM;
race_manager->setDifficulty(RaceManager::DIFFICULTY_MEDIUM);
}
else if (selection == "expert")
{
UserConfigParams::m_difficulty = RaceManager::DIFFICULTY_HARD;
race_manager->setDifficulty(RaceManager::DIFFICULTY_HARD);
}
else if (selection == "best")
{
if (unlock_manager->getCurrentSlot()->isLocked("difficulty_best"))
{
unlock_manager->playLockSound();
UserConfigParams::m_difficulty = RaceManager::DIFFICULTY_HARD;
race_manager->setDifficulty(RaceManager::DIFFICULTY_HARD);
w->setSelection(2, PLAYER_ID_GAME_MASTER);
w->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
}
else
{
UserConfigParams::m_difficulty = RaceManager::DIFFICULTY_BEST;
race_manager->setDifficulty(RaceManager::DIFFICULTY_BEST);
}
}
} }
else if (name == "gamemode") else if (name == "gamemode")
{ {
assignDifficulty();
DynamicRibbonWidget* w = dynamic_cast<DynamicRibbonWidget*>(widget); DynamicRibbonWidget* w = dynamic_cast<DynamicRibbonWidget*>(widget);
const std::string& selectedMode = w->getSelectionIDString(PLAYER_ID_GAME_MASTER); const std::string& selectedMode = w->getSelectionIDString(PLAYER_ID_GAME_MASTER);
@ -185,6 +153,47 @@ void RaceSetupScreen::eventCallback(Widget* widget, const std::string& name, con
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void RaceSetupScreen::assignDifficulty()
{
RibbonWidget* difficulty = getWidget<RibbonWidget>("difficulty");
assert(difficulty != NULL);
const std::string& difficultySelection = difficulty->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (difficultySelection == "novice")
{
UserConfigParams::m_difficulty = RaceManager::DIFFICULTY_EASY;
race_manager->setDifficulty(RaceManager::DIFFICULTY_EASY);
}
else if (difficultySelection == "intermediate")
{
UserConfigParams::m_difficulty = RaceManager::DIFFICULTY_MEDIUM;
race_manager->setDifficulty(RaceManager::DIFFICULTY_MEDIUM);
}
else if (difficultySelection == "expert")
{
UserConfigParams::m_difficulty = RaceManager::DIFFICULTY_HARD;
race_manager->setDifficulty(RaceManager::DIFFICULTY_HARD);
}
else if (difficultySelection == "best")
{
if (unlock_manager->getCurrentSlot()->isLocked("difficulty_best"))
{
unlock_manager->playLockSound();
UserConfigParams::m_difficulty = RaceManager::DIFFICULTY_HARD;
race_manager->setDifficulty(RaceManager::DIFFICULTY_HARD);
difficulty->setSelection(2, PLAYER_ID_GAME_MASTER);
difficulty->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
}
else
{
UserConfigParams::m_difficulty = RaceManager::DIFFICULTY_BEST;
race_manager->setDifficulty(RaceManager::DIFFICULTY_BEST);
}
}
}
// -----------------------------------------------------------------------------
void RaceSetupScreen::onGameModeChanged() void RaceSetupScreen::onGameModeChanged()
{ {
DynamicRibbonWidget* w2 = getWidget<DynamicRibbonWidget>("gamemode"); DynamicRibbonWidget* w2 = getWidget<DynamicRibbonWidget>("gamemode");

View File

@ -39,6 +39,8 @@ class RaceSetupScreen : public GUIEngine::Screen, public GUIEngine::ScreenSingle
void onGameModeChanged(); void onGameModeChanged();
void assignDifficulty();
public: public:
/** \brief implement callback from parent class GUIEngine::Screen */ /** \brief implement callback from parent class GUIEngine::Screen */

View File

@ -60,8 +60,7 @@ void ServerSelection::tearDown()
void ServerSelection::refresh() void ServerSelection::refresh()
{ {
m_refresh_request = ServersManager::acquire()->refreshRequest(); m_refresh_request = ServersManager::get()->refreshRequest();
ServersManager::release();
m_fake_refresh = (m_refresh_request == NULL ? true : false); m_fake_refresh = (m_refresh_request == NULL ? true : false);
m_server_list_widget->clear(); m_server_list_widget->clear();
m_server_list_widget->addItem("spacer", L""); m_server_list_widget->addItem("spacer", L"");
@ -113,11 +112,11 @@ void ServerSelection::init()
void ServerSelection::loadList() void ServerSelection::loadList()
{ {
m_server_list_widget->clear(); m_server_list_widget->clear();
ServersManager * manager = ServersManager::acquire(); ServersManager * manager = ServersManager::get();
manager->sort(m_sort_desc); manager->sort(m_sort_desc);
for(int i=0; i < manager->getNumServers(); i++) for(int i=0; i < manager->getNumServers(); i++)
{ {
Server * server = manager->getServerBySort(i); const Server * server = manager->getServerBySort(i);
core::stringw num_players; core::stringw num_players;
num_players.append(StringUtils::toWString(server->getCurrentPlayers())); num_players.append(StringUtils::toWString(server->getCurrentPlayers()));
num_players.append("/"); num_players.append("/");
@ -127,7 +126,6 @@ void ServerSelection::loadList()
row->push_back(new GUIEngine::ListWidget::ListCell(num_players,-1,1,true)); row->push_back(new GUIEngine::ListWidget::ListCell(num_players,-1,1,true));
m_server_list_widget->addItem("server", row); m_server_list_widget->addItem("server", row);
} }
ServersManager::release();
} // loadList } // loadList
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -162,10 +160,8 @@ void ServerSelection::eventCallback( GUIEngine::Widget* widget,
else if (name == m_server_list_widget->m_properties[GUIEngine::PROP_ID]) else if (name == m_server_list_widget->m_properties[GUIEngine::PROP_ID])
{ {
m_selected_index = m_server_list_widget->getSelectionID(); m_selected_index = m_server_list_widget->getSelectionID();
uint32_t server_id = ServersManager::acquire()->getServerBySort(m_selected_index)->getServerId(); uint32_t server_id = ServersManager::get()->getServerBySort(m_selected_index)->getServerId();
ServersManager::release(); uint32_t host_id = ServersManager::get()->getServerBySort(m_selected_index)->getHostId();
uint32_t host_id = ServersManager::acquire()->getServerBySort(m_selected_index)->getHostId();
ServersManager::release();
new ServerInfoDialog(server_id, host_id); new ServerInfoDialog(server_id, host_id);
} }

View File

@ -53,7 +53,7 @@ private:
/** \brief To check (and set) if sort order is descending **/ /** \brief To check (and set) if sort order is descending **/
bool m_sort_desc; bool m_sort_desc;
Online::ServersManager::RefreshRequest * m_refresh_request; const Online::ServersManager::RefreshRequest * m_refresh_request;
bool m_fake_refresh; bool m_fake_refresh;
void refresh(); void refresh();

View File

@ -121,6 +121,7 @@ Track::Track(const std::string &filename)
m_minimap_x_scale = 1.0f; m_minimap_x_scale = 1.0f;
m_minimap_y_scale = 1.0f; m_minimap_y_scale = 1.0f;
m_all_nodes.clear(); m_all_nodes.clear();
m_all_physics_only_nodes.clear();
m_all_cached_meshes.clear(); m_all_cached_meshes.clear();
loadTrackInfo(); loadTrackInfo();
} // Track } // Track
@ -182,6 +183,7 @@ void Track::cleanup()
irr_driver->removeNode(m_all_nodes[i]); irr_driver->removeNode(m_all_nodes[i]);
} }
m_all_nodes.clear(); m_all_nodes.clear();
m_all_physics_only_nodes.clear();
m_all_emitters.clearAndDeleteAll(); m_all_emitters.clearAndDeleteAll();
@ -963,6 +965,8 @@ bool Track::loadMainTrack(const XMLNode &root)
model_name=""; model_name="";
n->get("model", &model_name); n->get("model", &model_name);
full_path = m_root+model_name; full_path = m_root+model_name;
std::string interaction;
n->get("interaction", &interaction);
// a special challenge orb object for overworld // a special challenge orb object for overworld
std::string challenge; std::string challenge;
@ -1043,7 +1047,6 @@ bool Track::loadMainTrack(const XMLNode &root)
scene_node->setPosition(xyz); scene_node->setPosition(xyz);
scene_node->setRotation(hpr); scene_node->setRotation(hpr);
scene_node->setScale(scale); scene_node->setScale(scale);
#ifdef DEBUG #ifdef DEBUG
std::string debug_name = model_name+" (static track-object)"; std::string debug_name = model_name+" (static track-object)";
scene_node->setName(debug_name.c_str()); scene_node->setName(debug_name.c_str());
@ -1125,7 +1128,10 @@ bool Track::loadMainTrack(const XMLNode &root)
} }
else else
{ {
m_all_nodes.push_back( scene_node ); if(interaction=="physics-only")
m_all_physics_only_nodes.push_back( scene_node );
else
m_all_nodes.push_back( scene_node );
} }
} }
@ -1146,6 +1152,16 @@ bool Track::loadMainTrack(const XMLNode &root)
{ {
convertTrackToBullet(m_all_nodes[i]); convertTrackToBullet(m_all_nodes[i]);
} }
// Now convert all objects that are only used for the physics
// (like invisible walls).
for(unsigned int i=0; i<m_all_physics_only_nodes.size(); i++)
{
convertTrackToBullet(m_all_physics_only_nodes[i]);
irr_driver->removeNode(m_all_physics_only_nodes[i]);
}
m_all_physics_only_nodes.clear();
if (m_track_mesh == NULL) if (m_track_mesh == NULL)
{ {
Log::fatal("track", "m_track_mesh == NULL, cannot loadMainTrack\n"); Log::fatal("track", "m_track_mesh == NULL, cannot loadMainTrack\n");
@ -2076,17 +2092,17 @@ bool Track::findGround(AbstractKart *kart)
} }
btTransform t = kart->getBody()->getCenterOfMassTransform(); btTransform t = kart->getBody()->getCenterOfMassTransform();
// The computer offset is slightly too large, it should take // The computer offset is slightly too large, it should take
// the default suspension rest insteat of suspension rest (i.e. the // the default suspension rest insteat of suspension rest (i.e. the
// length of the suspension with the weight of the kart resting on // length of the suspension with the weight of the kart resting on
// it). On the other hand this initial bouncing looks nice imho // it). On the other hand this initial bouncing looks nice imho
// - so I'll leave it in for now. // - so I'll leave it in for now.
float offset = kart->getKartProperties()->getSuspensionRest() + float offset = kart->getKartProperties()->getSuspensionRest() +
kart->getKartProperties()->getWheelRadius(); kart->getKartProperties()->getWheelRadius();
t.setOrigin(hit_point+Vec3(0, offset, 0) ); t.setOrigin(hit_point+Vec3(0, offset, 0) );
kart->getBody()->setCenterOfMassTransform(t); kart->getBody()->setCenterOfMassTransform(t);
kart->setTrans(t); kart->setTrans(t);
return true; return true;
} // findGround } // findGround

View File

@ -174,8 +174,14 @@ private:
/** The base dir of all files of this track. */ /** The base dir of all files of this track. */
std::string m_root; std::string m_root;
std::vector<std::string> m_groups; std::vector<std::string> m_groups;
/** The list of all nodes. */
std::vector<scene::ISceneNode*> m_all_nodes; std::vector<scene::ISceneNode*> m_all_nodes;
/** The list of all nodes that are to be converted into physics,
* but not to be drawn (e.g. invisible walls). */
std::vector<scene::ISceneNode*> m_all_physics_only_nodes;
/** The list of all meshes that are loaded from disk, which means /** The list of all meshes that are loaded from disk, which means
* that those meshes are being cached by irrlicht, and need to be freed. */ * that those meshes are being cached by irrlicht, and need to be freed. */
std::vector<scene::IMesh*> m_all_cached_meshes; std::vector<scene::IMesh*> m_all_cached_meshes;

View File

@ -90,7 +90,7 @@ public:
TrackObjectPresentation* presentation, TrackObjectPresentation* presentation,
bool is_dynamic, bool is_dynamic,
const PhysicalObject::Settings* physicsSettings); const PhysicalObject::Settings* physicsSettings);
~TrackObject(); virtual ~TrackObject();
virtual void update(float dt); virtual void update(float dt);
virtual void reset(); virtual void reset();
/** To finish object constructions. Called after the track model /** To finish object constructions. Called after the track model

View File

@ -20,6 +20,7 @@
#ifndef HEADER_LOG_HPP #ifndef HEADER_LOG_HPP
#define HEADER_LOG_HPP #define HEADER_LOG_HPP
#include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -66,7 +67,9 @@ public:
static void printMessage(int level, const char *component, static void printMessage(int level, const char *component,
const char *format, VALIST va_list); const char *format, VALIST va_list);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** A simple macro to define the various log functions. */ /** A simple macro to define the various log functions.
* Note that an assert is added so that a debugger is triggered
* when debugging. */
#define LOG(NAME, LEVEL) \ #define LOG(NAME, LEVEL) \
static void NAME(const char *component, const char *format, ...) \ static void NAME(const char *component, const char *format, ...) \
{ \ { \
@ -76,7 +79,11 @@ public:
printMessage(LEVEL, component, format, args); \ printMessage(LEVEL, component, format, args); \
va_end(args); \ va_end(args); \
\ \
if (LEVEL == LL_FATAL) exit(1); \ if (LEVEL == LL_FATAL) \
{ \
assert(false); \
exit(1); \
} \
} }
LOG(verbose, LL_VERBOSE); LOG(verbose, LL_VERBOSE);
LOG(debug, LL_DEBUG); LOG(debug, LL_DEBUG);

View File

@ -19,9 +19,11 @@
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
#include "utils/log.hpp"
#include "coreutil.h" #include "coreutil.h"
#include "math.h" #include <math.h>
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <stdio.h> #include <stdio.h>
@ -191,14 +193,14 @@ namespace StringUtils
} }
catch (std::exception& e) catch (std::exception& e)
{ {
fprintf(stderr, Log::error("StringUtils",
"Fatal error in split(std::string) : %s @ line %i : %s\n", "Error in split(std::string) : %s @ line %i : %s.",
__FILE__, __LINE__, e.what()); __FILE__, __LINE__, e.what());
printf("Splitting %s\n", s.c_str()); Log::error("StringUtils", "Splitting '%s'.", s.c_str());
for (int n=0; n<(int)result.size(); n++) for (int n=0; n<(int)result.size(); n++)
{ {
printf("Split : %s\n", result[n].c_str()); Log::error("StringUtils", "Split : %s", result[n].c_str());
} }
assert(false); // in debug mode, trigger debugger assert(false); // in debug mode, trigger debugger
@ -253,10 +255,9 @@ namespace StringUtils
catch (std::exception& e) catch (std::exception& e)
{ {
(void)e; // avoid warning about unused variable (void)e; // avoid warning about unused variable
fprintf(stderr, Log::fatal("StringUtils",
"Fatal error in split(stringw) : %s @ line %i : %s\n", "Fatal error in split(stringw) : %s @ line %i : '%s'.",
__FILE__, __LINE__, e.what()); __FILE__, __LINE__, e.what());
assert(false); // in dbug mode, trigger debugger
exit(1); exit(1);
} }
} // split } // split
@ -310,8 +311,9 @@ namespace StringUtils
catch (std::exception& e) catch (std::exception& e)
{ {
(void)e; // avoid warning about unused variable (void)e; // avoid warning about unused variable
fprintf(stderr, "Fatal error in splitPath : %s @ line %i\n", Log::fatal("StringUtils",
__FILE__, __LINE__); "Fatal error in splitPath : %s @ line %i: '%s'.",
__FILE__, __LINE__, path.c_str());
exit(1); exit(1);
} }
} // splitPath } // splitPath
@ -340,10 +342,10 @@ namespace StringUtils
{ {
if (insertValID >= all_vals.size()) if (insertValID >= all_vals.size())
{ {
fprintf(stderr, Log::warn("StringUtils",
"[StringUtils::insertValues] ERROR: " "insertValues: "
"Invalid number of arguments in '%s'\n", "Invalid number of arguments in '%s'.",
s.c_str()); s.c_str());
new_string += "??" + sv[i].substr(2); new_string += "??" + sv[i].substr(2);
} }
else else
@ -358,9 +360,9 @@ namespace StringUtils
const unsigned int index = sv[i][1] - '0'; const unsigned int index = sv[i][1] - '0';
if (index >= all_vals.size()) if (index >= all_vals.size())
{ {
fprintf(stderr,"[StringUtils::insertValues] ERROR:" Log::warn("StringUtils", "insertValues: "
" Invalid argument index in '%s' " " Invalid argument index in '%s' "
"for %i\n", s.c_str(), index); "for %i.", s.c_str(), index);
new_string += "??" + sv[i].substr(2); new_string += "??" + sv[i].substr(2);
} }
else else
@ -379,8 +381,9 @@ namespace StringUtils
catch (std::exception& e) catch (std::exception& e)
{ {
(void)e; // avoid warning about unused variable (void)e; // avoid warning about unused variable
fprintf(stderr, "Fatal error in insertValues(std::string) : %s @ " Log::fatal("StringUtils",
"line %i\n", __FILE__, __LINE__); "Fatal error in insertValues(std::string) : %s @ "
"line %i: '%s'", __FILE__, __LINE__, s.c_str());
exit(1); exit(1);
} }
} }
@ -411,10 +414,9 @@ namespace StringUtils
{ {
if (insertValID >= all_vals.size()) if (insertValID >= all_vals.size())
{ {
fprintf(stderr, Log::warn("StringUtils", "insertValues: "
"[StringUtils::insertValues] ERROR: " "Invalid number of arguments in '%s'\n",
"Invalid number of arguments in '%s'\n", irr::core::stringc(s.c_str()).c_str());
irr::core::stringc(s.c_str()).c_str());
new_string += "??"; new_string += "??";
new_string += sv[i].subString(2, sv[i].size()-2); new_string += sv[i].subString(2, sv[i].size()-2);
} }
@ -442,11 +444,10 @@ namespace StringUtils
- '0' + delta; - '0' + delta;
if (index >= all_vals.size()) if (index >= all_vals.size())
{ {
fprintf(stderr, Log::warn("StringUtils", "insertValues: "
"[StringUtils::insertValues] ERROR: " "Invalid argument ID in '%s' : %i\n",
"Invalid argument ID in '%s' : %i\n", irr::core::stringc(s.c_str()).c_str(),
irr::core::stringc(s.c_str()).c_str(), index);
index);
new_string += "??"; new_string += "??";
new_string += rest; new_string += rest;
} }
@ -466,9 +467,9 @@ namespace StringUtils
catch (std::exception& e) catch (std::exception& e)
{ {
(void)e; // avoid warning about unused variable (void)e; // avoid warning about unused variable
fprintf(stderr, Log::fatal("StringUtils",
"Fatal error in insertValues(stringw) : %s @ line %i\n", "Fatal error in insertValues(stringw) : %s @ line %i.",
__FILE__, __LINE__); __FILE__, __LINE__);
exit(1); exit(1);
} }
} }
@ -599,10 +600,9 @@ namespace StringUtils
} }
else else
{ {
fprintf(stderr, Log::warn("StringUtils", "non-numeric HTML "
"[StringUtils] WARNING: non-numeric HTML " "entity not supported in '%s'.",
"entity not supported in '%s'\n", input.c_str());
input.c_str());
} }
state = NORMAL; state = NORMAL;
} }

View File

@ -21,11 +21,18 @@
#include <pthread.h> #include <pthread.h>
template<typename TYPE> class ISynchronised
{
public :
virtual ~ISynchronised() {}
virtual void lock() const = 0 ;
virtual void unlock() const = 0;
};
/** A variable that is automatically synchronised using pthreads mutex. /** A variable that is automatically synchronised using pthreads mutex.
*/ */
class Synchronised template<typename TYPE>
class Synchronised : public ISynchronised
{ {
private: private:
/** The mutex to protect this variable with. */ /** The mutex to protect this variable with. */
@ -97,11 +104,11 @@ public:
/** Locks the mutex. Note that calls to get() or set() will fail, since /** Locks the mutex. Note that calls to get() or set() will fail, since
* they will try to lock the mutex as well! * they will try to lock the mutex as well!
*/ */
void lock() { pthread_mutex_lock(&m_mutex); } void lock() const { pthread_mutex_lock(&m_mutex); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Unlocks the mutex. /** Unlocks the mutex.
*/ */
void unlock() {pthread_mutex_unlock(&m_mutex); } void unlock() const {pthread_mutex_unlock(&m_mutex); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Gives access to the mutex, which can then be used in other pthread /** Gives access to the mutex, which can then be used in other pthread
* calls (e.g. pthread_cond_wait). * calls (e.g. pthread_cond_wait).
@ -113,5 +120,21 @@ private:
void operator=(const Synchronised<TYPE>& v) {} void operator=(const Synchronised<TYPE>& v) {}
}; };
#define MutexLocker(x) MutexLockerHelper __dummy(x);
class MutexLockerHelper
{
const ISynchronised * m_synchronised;
public:
MutexLockerHelper(const ISynchronised & synchronised){
m_synchronised = &synchronised;
m_synchronised->lock();
}
~MutexLockerHelper(){
m_synchronised->unlock();
}
};
#endif #endif