Synchronised race results menu, single races in LAN
mode can now be restarted (GP and FTL modes are still to be done). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2307 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
44e9335baa
commit
1809dd1da1
@ -43,6 +43,8 @@ supertuxkart_SOURCES = main.cpp \
|
|||||||
network/kart_control_message.hpp network/kart_control_message.cpp \
|
network/kart_control_message.hpp network/kart_control_message.cpp \
|
||||||
network/flyable_info.hpp network/herring_info.hpp \
|
network/flyable_info.hpp network/herring_info.hpp \
|
||||||
network/race_state.hpp network/race_state.cpp \
|
network/race_state.hpp network/race_state.cpp \
|
||||||
|
network/race_result_message.hpp network/race_result_message.cpp \
|
||||||
|
network/race_result_ack_message \
|
||||||
audio/music.hpp \
|
audio/music.hpp \
|
||||||
audio/music_information.cpp audio/music_information.hpp \
|
audio/music_information.cpp audio/music_information.hpp \
|
||||||
audio/music_ogg.cpp audio/music_ogg.hpp \
|
audio/music_ogg.cpp audio/music_ogg.hpp \
|
||||||
|
@ -60,7 +60,8 @@ CharSel::CharSel(int whichPlayer)
|
|||||||
// in the server (even when NW_NONE). This if condition
|
// in the server (even when NW_NONE). This if condition
|
||||||
// needs to be checked (otherwise ghost karts and
|
// needs to be checked (otherwise ghost karts and
|
||||||
// a ghost camera will appear)
|
// a ghost camera will appear)
|
||||||
if(network_manager->getState()==NetworkManager::NS_NONE ||
|
m_first_frame = true;
|
||||||
|
if(network_manager->getState()==NetworkManager::NS_MAIN_MENU ||
|
||||||
network_manager->getMode()==NetworkManager::NW_NONE)
|
network_manager->getMode()==NetworkManager::NW_NONE)
|
||||||
network_manager->switchToCharacterSelection();
|
network_manager->switchToCharacterSelection();
|
||||||
|
|
||||||
@ -336,8 +337,7 @@ void CharSel::update(float dt)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool first=true;
|
if(m_first_frame)
|
||||||
if(first)
|
|
||||||
{
|
{
|
||||||
// Switch group will update the list of selected karts, i.e. use the
|
// Switch group will update the list of selected karts, i.e. use the
|
||||||
// information about kart availability just received from the server
|
// information about kart availability just received from the server
|
||||||
@ -351,7 +351,7 @@ void CharSel::update(float dt)
|
|||||||
widget_manager->showWgt(WTOK_NAME0+i);
|
widget_manager->showWgt(WTOK_NAME0+i);
|
||||||
widget_manager->showWgt(WTOK_RACER0+i);
|
widget_manager->showWgt(WTOK_RACER0+i);
|
||||||
}
|
}
|
||||||
first=false;
|
m_first_frame = false;
|
||||||
updateScrollPosition();
|
updateScrollPosition();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,8 @@ private:
|
|||||||
int m_player_index;
|
int m_player_index;
|
||||||
int m_offset; // index of first racer displayed
|
int m_offset; // index of first racer displayed
|
||||||
unsigned int m_num_entries; // number of entries to display
|
unsigned int m_num_entries; // number of entries to display
|
||||||
|
/** Helps to switch off the displayed text once only. */
|
||||||
|
bool m_first_frame;
|
||||||
std::vector<int> m_index_avail_karts;
|
std::vector<int> m_index_avail_karts;
|
||||||
static const unsigned int m_max_entries=7;
|
static const unsigned int m_max_entries=7;
|
||||||
void updateScrollPosition();
|
void updateScrollPosition();
|
||||||
|
@ -140,7 +140,7 @@ void NetworkGUI::select()
|
|||||||
network_manager->setMode(NetworkManager::NW_NONE);
|
network_manager->setMode(NetworkManager::NW_NONE);
|
||||||
// Disable accepting of clients
|
// Disable accepting of clients
|
||||||
if(network_manager->getMode()==NetworkManager::NW_SERVER)
|
if(network_manager->getMode()==NetworkManager::NW_SERVER)
|
||||||
network_manager->setState(NetworkManager::NS_NONE);
|
network_manager->setState(NetworkManager::NS_MAIN_MENU);
|
||||||
// Leave menu.
|
// Leave menu.
|
||||||
menu_manager->popMenu();
|
menu_manager->popMenu();
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ void RaceGUI::drawPlayerIcons (const KartIconDisplayInfo* info)
|
|||||||
Material *last_players_gst = 0;
|
Material *last_players_gst = 0;
|
||||||
|
|
||||||
int bFirst = 1;
|
int bFirst = 1;
|
||||||
const int kart_amount = race_manager->getNumKarts();
|
const unsigned int kart_amount = race_manager->getNumKarts();
|
||||||
for(unsigned int i = 0; i < kart_amount ; i++)
|
for(unsigned int i = 0; i < kart_amount ; i++)
|
||||||
{
|
{
|
||||||
Kart* kart = RaceManager::getKart(i);
|
Kart* kart = RaceManager::getKart(i);
|
||||||
|
@ -29,21 +29,15 @@
|
|||||||
#include "unlock_manager.hpp"
|
#include "unlock_manager.hpp"
|
||||||
#include "translation.hpp"
|
#include "translation.hpp"
|
||||||
#include "modes/world.hpp"
|
#include "modes/world.hpp"
|
||||||
|
#include "network/network_manager.hpp"
|
||||||
enum WidgetTokens
|
|
||||||
{
|
|
||||||
WTOK_CONTINUE,
|
|
||||||
WTOK_RESTART_RACE,
|
|
||||||
WTOK_SETUP_NEW_RACE,
|
|
||||||
WTOK_RESULTS,
|
|
||||||
WTOK_FIRST_RESULT,
|
|
||||||
WTOK_FIRST_IMAGE=1000,
|
|
||||||
WTOK_HIGHSCORES=2000,
|
|
||||||
WTOK_FIRST_HIGHSCORE=2001,
|
|
||||||
};
|
|
||||||
|
|
||||||
RaceResultsGUI::RaceResultsGUI()
|
RaceResultsGUI::RaceResultsGUI()
|
||||||
{
|
{
|
||||||
|
m_first_time = true;
|
||||||
|
m_selected_widget = WTOK_NONE;
|
||||||
|
|
||||||
|
// Switch to barrier mode: server waits for ack from each client
|
||||||
|
network_manager->beginRaceResultBarrier();
|
||||||
Widget *bottom_of_list;
|
Widget *bottom_of_list;
|
||||||
|
|
||||||
if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER)
|
if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER)
|
||||||
@ -51,6 +45,15 @@ RaceResultsGUI::RaceResultsGUI()
|
|||||||
else
|
else
|
||||||
bottom_of_list = displayRaceResults();
|
bottom_of_list = displayRaceResults();
|
||||||
|
|
||||||
|
// If it's a server, the user can only select 'ok', since the
|
||||||
|
// server does all the game mode selection etc.
|
||||||
|
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
||||||
|
{
|
||||||
|
Widget *w=widget_manager->addTextButtonWgt( WTOK_CONTINUE, 60, 7, _("OK") );
|
||||||
|
w->setPosition(WGT_DIR_CENTER, 0, NULL, WGT_DIR_UNDER_WIDGET, 0.05f, bottom_of_list);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// If a new feature was unlocked, only offer 'continue' otherwise add the
|
// If a new feature was unlocked, only offer 'continue' otherwise add the
|
||||||
// full menu choices. The new feature menu returns to this menu, and will
|
// full menu choices. The new feature menu returns to this menu, and will
|
||||||
// then display the whole menu.
|
// then display the whole menu.
|
||||||
@ -80,7 +83,7 @@ RaceResultsGUI::RaceResultsGUI()
|
|||||||
w->setPosition(WGT_DIR_CENTER, 0, NULL, WGT_DIR_UNDER_WIDGET, 0, w_prev);
|
w->setPosition(WGT_DIR_CENTER, 0, NULL, WGT_DIR_UNDER_WIDGET, 0, w_prev);
|
||||||
}
|
}
|
||||||
} // if !unlock_manager has something unlocked*/
|
} // if !unlock_manager has something unlocked*/
|
||||||
|
} // if not server
|
||||||
widget_manager->layout(WGT_AREA_ALL);
|
widget_manager->layout(WGT_AREA_ALL);
|
||||||
|
|
||||||
} // RaceResultsGUI
|
} // RaceResultsGUI
|
||||||
@ -252,6 +255,10 @@ RaceResultsGUI::~RaceResultsGUI()
|
|||||||
} // ~RaceResultsGUI
|
} // ~RaceResultsGUI
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
/** If an item is selected, store the selection to be handled in the next
|
||||||
|
* update call. This is necessary for network support so that the right
|
||||||
|
* action is executed once clients and server are all synchronised.
|
||||||
|
*/
|
||||||
void RaceResultsGUI::select()
|
void RaceResultsGUI::select()
|
||||||
{
|
{
|
||||||
// Push the unlocked-feature menu in for now
|
// Push the unlocked-feature menu in for now
|
||||||
@ -262,7 +269,71 @@ void RaceResultsGUI::select()
|
|||||||
menu_manager->pushMenu(MENUID_UNLOCKED_FEATURE);
|
menu_manager->pushMenu(MENUID_UNLOCKED_FEATURE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch( widget_manager->getSelectedWgt() )
|
// The selected token is saved here, which triggers a change of the text
|
||||||
|
// in update().
|
||||||
|
m_selected_widget = (WidgetTokens)widget_manager->getSelectedWgt();
|
||||||
|
|
||||||
|
// Clients send the ack to the server
|
||||||
|
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
||||||
|
network_manager->sendRaceResultAck();
|
||||||
|
|
||||||
|
} // select
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void RaceResultsGUI::handle(GameAction ga, int value)
|
||||||
|
{
|
||||||
|
// Attempts to close the menu are silently discarded
|
||||||
|
// since they do not make sense at this point.
|
||||||
|
if (ga == GA_LEAVE)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
BaseGUI::handle(ga, value);
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** Sets the selected token. This is used on the clients to allow the
|
||||||
|
* NetworkManager to set the widget selected on the server. The clients will
|
||||||
|
* then be able to select the correct next menu.
|
||||||
|
* \param token Token to set as being selected.
|
||||||
|
*/
|
||||||
|
void RaceResultsGUI::setSelectedWidget(int token)
|
||||||
|
{
|
||||||
|
m_selected_widget = (WidgetTokens)token;
|
||||||
|
} // setSelectedToken
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** This is used on the client and server to display a message while waiting
|
||||||
|
* in a barrier for clients and server to ack the display.
|
||||||
|
*/
|
||||||
|
void RaceResultsGUI::update(float dt)
|
||||||
|
{
|
||||||
|
BaseGUI::update(dt);
|
||||||
|
// If an item is selected (for the first time), change the text
|
||||||
|
// so that the user has feedback about his selection.
|
||||||
|
if(m_selected_widget!=WTOK_NONE && m_first_time)
|
||||||
|
{
|
||||||
|
m_first_time = false;
|
||||||
|
// User feedback on first selection: display message, and on the
|
||||||
|
// server remove unnecessary widgets.
|
||||||
|
widget_manager->setWgtText(WTOK_CONTINUE, _("Synchronising."));
|
||||||
|
if(network_manager->getMode()==NetworkManager::NW_SERVER)
|
||||||
|
{
|
||||||
|
widget_manager->hideWgt(WTOK_RESTART_RACE);
|
||||||
|
widget_manager->hideWgt(WTOK_SETUP_NEW_RACE);
|
||||||
|
}
|
||||||
|
} // m_selected_token defined and not first time
|
||||||
|
|
||||||
|
// Wait till the barrier is finished. On the server this is the case when
|
||||||
|
// the state ie MAIN_MENU, on the client when it is wait_for_available_characters.
|
||||||
|
if(network_manager->getState()!=NetworkManager::NS_MAIN_MENU &&
|
||||||
|
network_manager->getState()!=NetworkManager::NS_WAIT_FOR_AVAILABLE_CHARACTERS )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Send selected menu to all clients
|
||||||
|
if(m_selected_widget!=WTOK_NONE &&
|
||||||
|
network_manager->getMode()==NetworkManager::NW_SERVER)
|
||||||
|
network_manager->sendRaceResultAck(m_selected_widget);
|
||||||
|
|
||||||
|
switch(m_selected_widget)
|
||||||
{
|
{
|
||||||
case WTOK_CONTINUE:
|
case WTOK_CONTINUE:
|
||||||
// Gets called when:
|
// Gets called when:
|
||||||
@ -286,17 +357,6 @@ void RaceResultsGUI::select()
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} // select
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void
|
|
||||||
RaceResultsGUI::handle(GameAction ga, int value)
|
|
||||||
{
|
|
||||||
// Attempts to close the menu are silently discarded
|
|
||||||
// since they do not make sense at this point.
|
|
||||||
if (ga == GA_LEAVE)
|
|
||||||
return;
|
|
||||||
else
|
|
||||||
BaseGUI::handle(ga, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
} // update
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
@ -28,9 +28,27 @@
|
|||||||
/** GUI that shows the RaceResults, times and such */
|
/** GUI that shows the RaceResults, times and such */
|
||||||
class RaceResultsGUI : public BaseGUI
|
class RaceResultsGUI : public BaseGUI
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
/** Widgets. WTOK_NONE is used for detecting in update when
|
||||||
|
* a selection was made (see m_selected_token). */
|
||||||
|
enum WidgetTokens
|
||||||
|
{
|
||||||
|
WTOK_NONE,
|
||||||
|
WTOK_CONTINUE,
|
||||||
|
WTOK_RESTART_RACE,
|
||||||
|
WTOK_SETUP_NEW_RACE,
|
||||||
|
WTOK_RESULTS,
|
||||||
|
WTOK_FIRST_RESULT,
|
||||||
|
WTOK_FIRST_IMAGE = 1000,
|
||||||
|
WTOK_HIGHSCORES = 2000,
|
||||||
|
WTOK_FIRST_HIGHSCORE = 2001,
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
std::vector<int> m_order;
|
std::vector<int> m_order;
|
||||||
|
bool m_first_time;
|
||||||
|
/** The widget selected by the user, so that the right action can be done
|
||||||
|
* once clients and server are synchronised. */
|
||||||
|
WidgetTokens m_selected_widget;
|
||||||
Widget *displayLeaderResults();
|
Widget *displayLeaderResults();
|
||||||
Widget *displayRaceResults();
|
Widget *displayRaceResults();
|
||||||
Widget *displayKartList(unsigned int from, unsigned int to,
|
Widget *displayKartList(unsigned int from, unsigned int to,
|
||||||
@ -39,10 +57,10 @@ private:
|
|||||||
public:
|
public:
|
||||||
RaceResultsGUI();
|
RaceResultsGUI();
|
||||||
~RaceResultsGUI();
|
~RaceResultsGUI();
|
||||||
|
|
||||||
void handle(GameAction, int);
|
void handle(GameAction, int);
|
||||||
|
|
||||||
void select();
|
void select();
|
||||||
|
virtual void update(float dt);
|
||||||
|
void setSelectedWidget(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1090,6 +1090,10 @@
|
|||||||
RelativePath="..\..\network\race_info_message.cpp"
|
RelativePath="..\..\network\race_info_message.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\network\race_result_message.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\network\race_state.cpp"
|
RelativePath="..\..\network\race_state.cpp"
|
||||||
>
|
>
|
||||||
@ -1660,6 +1664,14 @@
|
|||||||
RelativePath="..\..\network\race_info_message.hpp"
|
RelativePath="..\..\network\race_info_message.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\network\race_result_ack_message.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\network\race_result_message.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\network\race_start_message.hpp"
|
RelativePath="..\..\network\race_start_message.hpp"
|
||||||
>
|
>
|
||||||
|
@ -385,6 +385,7 @@ void Kart::reset()
|
|||||||
m_rescue = false;
|
m_rescue = false;
|
||||||
TerrainInfo::update(getXYZ());
|
TerrainInfo::update(getXYZ());
|
||||||
} // reset
|
} // reset
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void Kart::raceFinished(float time)
|
void Kart::raceFinished(float time)
|
||||||
{
|
{
|
||||||
|
@ -115,6 +115,9 @@ void MainLoop::run()
|
|||||||
|
|
||||||
// Server: Send the current position and previous controls to all clients
|
// Server: Send the current position and previous controls to all clients
|
||||||
// Client: send current controls to server
|
// Client: send current controls to server
|
||||||
|
// But don't do this if the race is in finish phase (otherwise
|
||||||
|
// messages can be mixed up in the race manager)
|
||||||
|
if(!race_manager->getWorld()->getClock().isFinishPhase())
|
||||||
network_manager->sendUpdates();
|
network_manager->sendUpdates();
|
||||||
music_on = false;
|
music_on = false;
|
||||||
if(user_config->m_profile) dt=1.0f/60.0f;
|
if(user_config->m_profile) dt=1.0f/60.0f;
|
||||||
@ -122,6 +125,11 @@ void MainLoop::run()
|
|||||||
// which can cause the camera to significantly tilt
|
// which can cause the camera to significantly tilt
|
||||||
scene->draw(RaceManager::getWorld()->getPhase()==SETUP_PHASE ? 0.0f : dt);
|
scene->draw(RaceManager::getWorld()->getPhase()==SETUP_PHASE ? 0.0f : dt);
|
||||||
|
|
||||||
|
// Again, only receive updates if the race isn't over - once the
|
||||||
|
// race results are displayed (i.e. game is in finish phase)
|
||||||
|
// messages must be handled by the normal update of the network
|
||||||
|
// manager
|
||||||
|
if(!race_manager->getWorld()->getClock().isFinishPhase())
|
||||||
network_manager->receiveUpdates();
|
network_manager->receiveUpdates();
|
||||||
|
|
||||||
if ( RaceManager::getWorld()->getPhase() != LIMBO_PHASE)
|
if ( RaceManager::getWorld()->getPhase() != LIMBO_PHASE)
|
||||||
|
@ -72,7 +72,7 @@ void Clock::raceOver(const bool delay)
|
|||||||
m_phase = FINISH_PHASE;
|
m_phase = FINISH_PHASE;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void Clock::updateClock(const float dt)
|
void Clock::update(const float dt)
|
||||||
{
|
{
|
||||||
switch(m_phase)
|
switch(m_phase)
|
||||||
{
|
{
|
||||||
|
@ -113,7 +113,13 @@ public:
|
|||||||
|
|
||||||
// Note: GO_PHASE is both: start phase and race phase
|
// Note: GO_PHASE is both: start phase and race phase
|
||||||
bool isStartPhase() const { return m_phase<GO_PHASE; }
|
bool isStartPhase() const { return m_phase<GO_PHASE; }
|
||||||
bool isRacePhase() const { return m_phase>=GO_PHASE && m_phase<LIMBO_PHASE; }
|
bool isRacePhase() const { return m_phase>=GO_PHASE &&
|
||||||
|
m_phase<LIMBO_PHASE; }
|
||||||
|
/** While the race menu is being displayed, m_phase is limbo, and
|
||||||
|
* m_previous_phase is finish. So we have to test this case, too. */
|
||||||
|
bool isFinishPhase() const { return m_phase==FINISH_PHASE ||
|
||||||
|
(m_phase==LIMBO_PHASE &&
|
||||||
|
m_previous_phase==FINISH_PHASE);}
|
||||||
const Phase getPhase() const { return m_phase; }
|
const Phase getPhase() const { return m_phase; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,7 +132,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Call each frame, with the elapsed time as argument.
|
* Call each frame, with the elapsed time as argument.
|
||||||
*/
|
*/
|
||||||
void updateClock(const float dt);
|
void update(const float dt);
|
||||||
|
|
||||||
float getTime() const { return m_time; }
|
float getTime() const { return m_time; }
|
||||||
void setTime(const float time);
|
void setTime(const float time);
|
||||||
|
@ -35,10 +35,10 @@ FollowTheLeaderRace::~FollowTheLeaderRace()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark clock events
|
#pragma mark clock events
|
||||||
|
#endif
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void FollowTheLeaderRace::countdownReachedZero()
|
void FollowTheLeaderRace::countdownReachedZero()
|
||||||
{
|
{
|
||||||
@ -60,14 +60,14 @@ void FollowTheLeaderRace::onTerminate()
|
|||||||
World::terminateRace();
|
World::terminateRace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark overridden from World
|
#pragma mark overridden from World
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void FollowTheLeaderRace::update(float delta)
|
void FollowTheLeaderRace::update(float delta)
|
||||||
{
|
{
|
||||||
m_clock.updateClock(delta);
|
|
||||||
|
|
||||||
LinearWorld::update(delta);
|
LinearWorld::update(delta);
|
||||||
if(!m_clock.isRacePhase()) return;
|
if(!m_clock.isRacePhase()) return;
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ void FollowTheLeaderRace::update(float delta)
|
|||||||
if(!m_kart[i]->isEliminated())
|
if(!m_kart[i]->isEliminated())
|
||||||
race_manager->RaceFinished(m_kart[i], m_clock.getTime());
|
race_manager->RaceFinished(m_kart[i], m_clock.getTime());
|
||||||
|
|
||||||
m_clock.raceOver();
|
raceOver();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "gui/menu_manager.hpp"
|
#include "gui/menu_manager.hpp"
|
||||||
#include "translation.hpp"
|
#include "translation.hpp"
|
||||||
#include "audio/sound_manager.hpp"
|
#include "audio/sound_manager.hpp"
|
||||||
|
#include "network/network_manager.hpp"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
LinearWorld::LinearWorld() : World()
|
LinearWorld::LinearWorld() : World()
|
||||||
@ -196,6 +197,10 @@ void LinearWorld::doLapCounting ( KartInfo& kart_info, Kart* kart )
|
|||||||
if(kart_info.m_race_lap >= race_manager->getNumLaps() &&
|
if(kart_info.m_race_lap >= race_manager->getNumLaps() &&
|
||||||
race_manager->getMinorMode() != RaceManager::MINOR_MODE_FOLLOW_LEADER)
|
race_manager->getMinorMode() != RaceManager::MINOR_MODE_FOLLOW_LEADER)
|
||||||
{
|
{
|
||||||
|
// A client wait does not detect race finished by itself, it will
|
||||||
|
// receive a message from the server. So a client does not do
|
||||||
|
// anything here.
|
||||||
|
if(network_manager->getMode()!=NetworkManager::NW_CLIENT)
|
||||||
kart->raceFinished(RaceManager::getWorld()->getTime());
|
kart->raceFinished(RaceManager::getWorld()->getTime());
|
||||||
}
|
}
|
||||||
// Only do timings if original time was set properly. Driving backwards
|
// Only do timings if original time was set properly. Driving backwards
|
||||||
|
@ -32,8 +32,10 @@ StandardRace::~StandardRace()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark clock events
|
#pragma mark clock events
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void StandardRace::countdownReachedZero() { }
|
void StandardRace::countdownReachedZero() { }
|
||||||
@ -54,8 +56,10 @@ void StandardRace::onTerminate()
|
|||||||
World::terminateRace();
|
World::terminateRace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark overridden from World
|
#pragma mark overridden from World
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void StandardRace::restartRace()
|
void StandardRace::restartRace()
|
||||||
@ -65,15 +69,13 @@ void StandardRace::restartRace()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void StandardRace::update(float delta)
|
void StandardRace::update(float delta)
|
||||||
{
|
{
|
||||||
m_clock.updateClock(delta);
|
|
||||||
|
|
||||||
LinearWorld::update(delta);
|
LinearWorld::update(delta);
|
||||||
if(!m_clock.isRacePhase()) return;
|
if(!m_clock.isRacePhase()) return;
|
||||||
|
|
||||||
// All karts are finished
|
// All karts are finished
|
||||||
if(race_manager->getFinishedKarts() >= race_manager->getNumKarts() )
|
if(race_manager->getFinishedKarts() >= race_manager->getNumKarts() )
|
||||||
{
|
{
|
||||||
m_clock.raceOver();
|
raceOver();
|
||||||
if(user_config->m_profile<0) printProfileResultAndExit();
|
if(user_config->m_profile<0) printProfileResultAndExit();
|
||||||
unlock_manager->raceFinished();
|
unlock_manager->raceFinished();
|
||||||
} // if all karts are finished
|
} // if all karts are finished
|
||||||
@ -84,7 +86,7 @@ void StandardRace::update(float delta)
|
|||||||
{
|
{
|
||||||
// Set delay mode to have time for camera animation, and
|
// Set delay mode to have time for camera animation, and
|
||||||
// to give the AI some time to get non-estimated timings
|
// to give the AI some time to get non-estimated timings
|
||||||
m_clock.raceOver(true /* delay */);
|
raceOver(true /* delay */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,6 +257,7 @@ void World::resetAllKarts()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void World::update(float dt)
|
void World::update(float dt)
|
||||||
{
|
{
|
||||||
|
m_clock.update(dt);
|
||||||
// Clear race state so that new information can be stored
|
// Clear race state so that new information can be stored
|
||||||
race_state->clear();
|
race_state->clear();
|
||||||
if(user_config->m_replay_history) dt=history->GetNextDelta();
|
if(user_config->m_replay_history) dt=history->GetNextDelta();
|
||||||
@ -277,6 +278,14 @@ void World::update(float dt)
|
|||||||
callback_manager->update(dt);
|
callback_manager->update(dt);
|
||||||
}
|
}
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
void World::raceOver(bool delay)
|
||||||
|
{
|
||||||
|
m_clock.raceOver(delay);
|
||||||
|
if(network_manager->getMode()==NetworkManager::NW_SERVER)
|
||||||
|
network_manager->sendRaceResults();
|
||||||
|
} // raceOver
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
HighscoreEntry* World::getHighscores() const
|
HighscoreEntry* World::getHighscores() const
|
||||||
{
|
{
|
||||||
if(!m_use_highscores) return NULL;
|
if(!m_use_highscores) return NULL;
|
||||||
@ -307,7 +316,7 @@ void World::updateHighscores()
|
|||||||
// again by a faster kart in the same race), which might be confusing
|
// again by a faster kart in the same race), which might be confusing
|
||||||
// if we ever decide to display a message (e.g. during a race)
|
// if we ever decide to display a message (e.g. during a race)
|
||||||
unsigned int *index = new unsigned int[m_kart.size()];
|
unsigned int *index = new unsigned int[m_kart.size()];
|
||||||
const int kart_amount = m_kart.size();
|
const unsigned int kart_amount = m_kart.size();
|
||||||
for (unsigned int i=0; i<kart_amount; i++ )
|
for (unsigned int i=0; i<kart_amount; i++ )
|
||||||
{
|
{
|
||||||
index[m_kart[i]->getPosition()-1] = i;
|
index[m_kart[i]->getPosition()-1] = i;
|
||||||
|
@ -148,10 +148,10 @@ public:
|
|||||||
HighscoreEntry* getHighscores() const;
|
HighscoreEntry* getHighscores() const;
|
||||||
float getTime() const { return m_clock.getTime(); }
|
float getTime() const { return m_clock.getTime(); }
|
||||||
Phase getPhase() const { return m_clock.getPhase(); }
|
Phase getPhase() const { return m_clock.getPhase(); }
|
||||||
const Clock& getClock() const { return m_clock; }
|
const Clock &getClock() { return m_clock; }
|
||||||
|
/** Gets called when the race is about to finish (but with the option of adding
|
||||||
/** Called when race is over and should be terminated (mostly called by the clock).
|
* some delay to watch the end of the race. */
|
||||||
*/
|
void raceOver(bool delay=false);
|
||||||
virtual void terminateRace();
|
virtual void terminateRace();
|
||||||
|
|
||||||
/** Called to determine the default collectibles to give each player for this
|
/** Called to determine the default collectibles to give each player for this
|
||||||
|
@ -63,6 +63,8 @@ void Message::receive(ENetPacket* pkt, MessageType m)
|
|||||||
m_data_size = pkt->dataLength;
|
m_data_size = pkt->dataLength;
|
||||||
m_data = (char*)pkt->data;
|
m_data = (char*)pkt->data;
|
||||||
m_type = (MessageType)m_data[0];
|
m_type = (MessageType)m_data[0];
|
||||||
|
if(m_type!=m)
|
||||||
|
printf("type %d %d\n",m_type,m);
|
||||||
assert(m_type==m);
|
assert(m_type==m);
|
||||||
m_pos = 1;
|
m_pos = 1;
|
||||||
m_needs_destroy = true;
|
m_needs_destroy = true;
|
||||||
|
@ -43,10 +43,12 @@
|
|||||||
class Message
|
class Message
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/** Contains all tags used in identifying a message. */
|
||||||
enum MessageType {MT_CONNECT=1, MT_CHARACTER_INFO, MT_CHARACTER_CONFIRM,
|
enum MessageType {MT_CONNECT=1, MT_CHARACTER_INFO, MT_CHARACTER_CONFIRM,
|
||||||
MT_RACE_INFO, MT_RACE_START, MT_WORLD_LOADED,
|
MT_RACE_INFO, MT_RACE_START, MT_WORLD_LOADED,
|
||||||
MT_KART_INFO, MT_KART_CONTROL,
|
MT_KART_INFO, MT_KART_CONTROL, MT_RACE_STATE,
|
||||||
MT_RACE_STATE};
|
MT_RACE_RESULT, MT_RACE_RESULT_ACK
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
ENetPacket *m_pkt;
|
ENetPacket *m_pkt;
|
||||||
char *m_data;
|
char *m_data;
|
||||||
|
@ -18,6 +18,16 @@
|
|||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#include "network_manager.hpp"
|
#include "network_manager.hpp"
|
||||||
|
|
||||||
|
#include "stk_config.hpp"
|
||||||
|
#include "user_config.hpp"
|
||||||
|
#include "race_manager.hpp"
|
||||||
|
#include "kart_properties_manager.hpp"
|
||||||
|
#include "translation.hpp"
|
||||||
|
#include "gui/menu_manager.hpp"
|
||||||
|
#include "gui/char_sel.hpp"
|
||||||
|
#include "gui/race_results_gui.hpp"
|
||||||
|
#include "modes/world.hpp"
|
||||||
#include "network/connect_message.hpp"
|
#include "network/connect_message.hpp"
|
||||||
#include "network/character_info_message.hpp"
|
#include "network/character_info_message.hpp"
|
||||||
#include "network/character_selected_message.hpp"
|
#include "network/character_selected_message.hpp"
|
||||||
@ -27,13 +37,8 @@
|
|||||||
#include "network/race_state.hpp"
|
#include "network/race_state.hpp"
|
||||||
#include "network/kart_control_message.hpp"
|
#include "network/kart_control_message.hpp"
|
||||||
#include "network/character_confirm_message.hpp"
|
#include "network/character_confirm_message.hpp"
|
||||||
#include "stk_config.hpp"
|
#include "network/race_result_message.hpp"
|
||||||
#include "user_config.hpp"
|
#include "network/race_result_ack_message.hpp"
|
||||||
#include "race_manager.hpp"
|
|
||||||
#include "kart_properties_manager.hpp"
|
|
||||||
#include "translation.hpp"
|
|
||||||
#include "gui/menu_manager.hpp"
|
|
||||||
#include "gui/char_sel.hpp"
|
|
||||||
|
|
||||||
NetworkManager* network_manager = 0;
|
NetworkManager* network_manager = 0;
|
||||||
|
|
||||||
@ -272,6 +277,22 @@ void NetworkManager::handleMessageAtServer(ENetEvent *event)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NS_RACE_RESULT_BARRIER:
|
||||||
|
{
|
||||||
|
// Other message, esp. kart control, are silently ignored.
|
||||||
|
// FIXME: we might want to make sure that no such message actually arrives
|
||||||
|
if(Message::peekType(event->packet)!=Message::MT_RACE_RESULT_ACK)
|
||||||
|
{
|
||||||
|
enet_packet_destroy(event->packet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_barrier_count++;
|
||||||
|
if(m_barrier_count==(int)m_num_clients)
|
||||||
|
{
|
||||||
|
m_state = NS_MAIN_MENU;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: assert(0); // should not happen
|
default: assert(0); // should not happen
|
||||||
} // switch m_state
|
} // switch m_state
|
||||||
} // handleMessageAtServer
|
} // handleMessageAtServer
|
||||||
@ -347,6 +368,16 @@ void NetworkManager::handleMessageAtClient(ENetEvent *event)
|
|||||||
assert(false); // should never be here while racing
|
assert(false); // should never be here while racing
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NS_RACE_RESULT_BARRIER:
|
||||||
|
{
|
||||||
|
RaceResultAckMessage message(event->packet);
|
||||||
|
RaceResultsGUI *menu = dynamic_cast<RaceResultsGUI*>(menu_manager->getCurrentMenu());
|
||||||
|
if(menu)
|
||||||
|
menu->setSelectedWidget(message.getSelectedMenu());
|
||||||
|
|
||||||
|
m_state = NS_WAIT_FOR_AVAILABLE_CHARACTERS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
printf("received unknown message: type %d\n",
|
printf("received unknown message: type %d\n",
|
||||||
@ -592,6 +623,14 @@ void NetworkManager::receiveUpdates()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Test if it is a game over message:
|
||||||
|
if(Message::peekType(event.packet)==Message::MT_RACE_RESULT)
|
||||||
|
{
|
||||||
|
RaceResultMessage m(event.packet);
|
||||||
|
m_state = NS_WAIT_FOR_RACE_RESULT;
|
||||||
|
race_manager->getWorld()->raceOver();
|
||||||
|
return;
|
||||||
|
}
|
||||||
race_state->receive(event.packet);
|
race_state->receive(event.packet);
|
||||||
}
|
}
|
||||||
} // for i<num_messages
|
} // for i<num_messages
|
||||||
@ -628,3 +667,50 @@ void NetworkManager::waitForClientData()
|
|||||||
|
|
||||||
} // waitForClientData
|
} // waitForClientData
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Sends the race result (kart positions and finishing times) from the server
|
||||||
|
* to all clients. Clients keep on racing till they receive this message, and
|
||||||
|
* will then copy the server's race results to the race manager.
|
||||||
|
*/
|
||||||
|
void NetworkManager::sendRaceResults()
|
||||||
|
{
|
||||||
|
RaceResultMessage m;
|
||||||
|
broadcastToClients(m);
|
||||||
|
} // sendRaceResults
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Changes the mode to wait in a barrier for all clients and the server to
|
||||||
|
* acknowledge the result screen. The server waits for a message from all
|
||||||
|
* clients, upon which it sends a message to all clients. The clients wait
|
||||||
|
* for this message before continuing.
|
||||||
|
*/
|
||||||
|
void NetworkManager::beginRaceResultBarrier()
|
||||||
|
{
|
||||||
|
m_state = NS_RACE_RESULT_BARRIER;
|
||||||
|
|
||||||
|
if(m_mode==NW_SERVER)
|
||||||
|
{
|
||||||
|
m_barrier_count = 0;
|
||||||
|
// In case of no networking set the next state
|
||||||
|
if(m_num_clients == 0) m_state = NS_MAIN_MENU;
|
||||||
|
}
|
||||||
|
} // beginRaceResultBarrier
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Sends a race 'result acknowledge' message from the clients to the server,
|
||||||
|
* or from the server to the clients (in this case it contains the selected
|
||||||
|
* menu choice from the server).
|
||||||
|
*/
|
||||||
|
void NetworkManager::sendRaceResultAck(char menu_selection)
|
||||||
|
{
|
||||||
|
// Menu selection is actually not important for a client
|
||||||
|
RaceResultAckMessage m(menu_selection);
|
||||||
|
if (m_mode==NW_CLIENT)
|
||||||
|
{
|
||||||
|
sendToServer(m);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
broadcastToClients(m);
|
||||||
|
m_state = NS_MAIN_MENU;
|
||||||
|
}
|
||||||
|
} // sendRaceResultAck
|
||||||
|
@ -37,7 +37,7 @@ public:
|
|||||||
enum NetworkMode {NW_SERVER, NW_CLIENT, NW_NONE};
|
enum NetworkMode {NW_SERVER, NW_CLIENT, NW_NONE};
|
||||||
|
|
||||||
// States for the finite state machine. First for server:
|
// States for the finite state machine. First for server:
|
||||||
enum NetworkState {NS_NONE,
|
enum NetworkState {NS_MAIN_MENU, // before char sel gui
|
||||||
NS_ACCEPT_CONNECTIONS, // server: accept connections
|
NS_ACCEPT_CONNECTIONS, // server: accept connections
|
||||||
NS_WAIT_FOR_AVAILABLE_CHARACTERS, // client: wait for list
|
NS_WAIT_FOR_AVAILABLE_CHARACTERS, // client: wait for list
|
||||||
NS_ALL_REMOTE_CHARACTERS_DONE, // server: all client data received
|
NS_ALL_REMOTE_CHARACTERS_DONE, // server: all client data received
|
||||||
@ -48,7 +48,10 @@ public:
|
|||||||
NS_READY_SET_GO_BARRIER, // c&s: barrier before r.s.g.
|
NS_READY_SET_GO_BARRIER, // c&s: barrier before r.s.g.
|
||||||
NS_CHARACTER_SELECT, // c&s: character select in progress
|
NS_CHARACTER_SELECT, // c&s: character select in progress
|
||||||
NS_LOADING_WORLD, // client: loading world
|
NS_LOADING_WORLD, // client: loading world
|
||||||
NS_RACING};
|
NS_RACING,
|
||||||
|
NS_WAIT_FOR_RACE_RESULT, // clients: waiting for race results
|
||||||
|
NS_RACE_RESULT_BARRIER // Wait till all ack results
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
|
|
||||||
NetworkMode m_mode;
|
NetworkMode m_mode;
|
||||||
@ -108,6 +111,9 @@ public:
|
|||||||
void sendUpdates();
|
void sendUpdates();
|
||||||
void receiveUpdates();
|
void receiveUpdates();
|
||||||
void waitForClientData();
|
void waitForClientData();
|
||||||
|
void sendRaceResults();
|
||||||
|
void beginRaceResultBarrier();
|
||||||
|
void sendRaceResultAck(char menu_selection=-1);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NetworkManager *network_manager;
|
extern NetworkManager *network_manager;
|
||||||
|
59
src/network/race_result_ack_message.hpp
Executable file
59
src/network/race_result_ack_message.hpp
Executable file
@ -0,0 +1,59 @@
|
|||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2008 Joerg Henrichs
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#ifndef HEADER_RACE_RESULT_ACK_MESSAGE_HPP
|
||||||
|
#define HEADER_RACE_RESULT_ACK_MESSAGE_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "network/message.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
/** This message is sent from the clients to the server when the race result
|
||||||
|
* screen was acknowledged, and then from the server to all clients to
|
||||||
|
* finish synchronisation.
|
||||||
|
*/
|
||||||
|
class RaceResultAckMessage : public Message
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
char m_menu_selected;
|
||||||
|
public:
|
||||||
|
/** Constructor, creates an empty message
|
||||||
|
*/
|
||||||
|
RaceResultAckMessage(char menu_choice) : Message(Message::MT_RACE_RESULT_ACK)
|
||||||
|
{
|
||||||
|
allocate(getCharLength());
|
||||||
|
addChar(menu_choice);
|
||||||
|
} // RaceResultAckMessage
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Receives the ack message.
|
||||||
|
* \param pkt Received enet packet.
|
||||||
|
*/
|
||||||
|
RaceResultAckMessage(ENetPacket* pkt):Message(pkt, MT_RACE_RESULT_ACK)
|
||||||
|
{
|
||||||
|
m_menu_selected = getChar();
|
||||||
|
} // RaceResultAckMessage(EnetPacket)
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns the menu selected on the server after this message is received
|
||||||
|
* on a client. */
|
||||||
|
char getSelectedMenu() const {return m_menu_selected; }
|
||||||
|
|
||||||
|
}; // RaceResultAckMessageMessage
|
||||||
|
#endif
|
62
src/network/race_result_message.cpp
Executable file
62
src/network/race_result_message.cpp
Executable file
@ -0,0 +1,62 @@
|
|||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2008 Joerg Henrichs
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#include "network/race_result_message.hpp"
|
||||||
|
|
||||||
|
#include "race_manager.hpp"
|
||||||
|
#include "modes/world.hpp"
|
||||||
|
#include "kart.hpp"
|
||||||
|
|
||||||
|
/** Creates a message containing the finishing time and rank of each kart.
|
||||||
|
* This message is serialised so that it can be sent.
|
||||||
|
*/
|
||||||
|
RaceResultMessage::RaceResultMessage() : Message(MT_RACE_RESULT)
|
||||||
|
{
|
||||||
|
const unsigned int num_karts = race_manager->getNumKarts();
|
||||||
|
allocate(num_karts * (getFloatLength()+getCharLength()));
|
||||||
|
World *world = race_manager->getWorld();
|
||||||
|
for(unsigned int i=0; i<num_karts; i++)
|
||||||
|
{
|
||||||
|
const Kart *kart = world->getKart(i);
|
||||||
|
addFloat(kart->getFinishTime());
|
||||||
|
addChar(kart->getPosition());
|
||||||
|
} // for i in karts
|
||||||
|
} // RaceResultMessage
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** De-serialises a race result message and sets the appropriate results in
|
||||||
|
* the kart and the race manager.
|
||||||
|
* \param pkt The enet message paket.
|
||||||
|
*/
|
||||||
|
RaceResultMessage::RaceResultMessage(ENetPacket* pkt)
|
||||||
|
: Message(pkt, MT_RACE_RESULT)
|
||||||
|
{
|
||||||
|
const unsigned int num_karts = race_manager->getNumKarts();
|
||||||
|
World *world = race_manager->getWorld();
|
||||||
|
for(unsigned int i=0; i<num_karts; i++)
|
||||||
|
{
|
||||||
|
Kart *kart = world->getKart(i);
|
||||||
|
float time = getFloat();
|
||||||
|
char position = getChar();
|
||||||
|
kart->setPosition(position);
|
||||||
|
kart->raceFinished(time);
|
||||||
|
race_manager->RaceFinished(kart, time);
|
||||||
|
}
|
||||||
|
} // RaceResultMessage
|
||||||
|
|
46
src/network/race_result_message.hpp
Executable file
46
src/network/race_result_message.hpp
Executable file
@ -0,0 +1,46 @@
|
|||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2008 Joerg Henrichs
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#ifndef HEADER_RACE_RESULT_MESSAGE_HPP
|
||||||
|
#define HEADER_RACE_RESULT_MESSAGE_HPP
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "network/message.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
/** This message is from the server to all clients to inform them about the
|
||||||
|
* result of a race. The clients wait for this message before they finish
|
||||||
|
* a race.
|
||||||
|
*/
|
||||||
|
class RaceResultMessage : public Message
|
||||||
|
{
|
||||||
|
struct RaceResult {
|
||||||
|
float m_time;
|
||||||
|
int m_score;
|
||||||
|
}; // RaceResult
|
||||||
|
private:
|
||||||
|
std::vector<RaceResult> m_all_results;
|
||||||
|
public:
|
||||||
|
RaceResultMessage();
|
||||||
|
RaceResultMessage(ENetPacket* pkt);
|
||||||
|
void addRaceResult(int kart_id, float time, int points);
|
||||||
|
void getRaceResult(int kart_id, float &time, int &points);
|
||||||
|
}; // RaceResultMessage
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user