1) Character selection is now synchronsied between all clients and server (i.e.

a character can only be selected once, and is then not available for other
   players anymore).
2) Fixed restart race (which would finish the race after about 11 seconds)
3) Moved widget related classes into gui dir.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2264 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2008-09-13 07:09:36 +00:00
parent 7203ad76c9
commit 8a4a939980
23 changed files with 400 additions and 134 deletions

View File

@ -35,7 +35,7 @@ supertuxkart_SOURCES = main.cpp \
network/message.cpp network/message.hpp \
network/race_info_message.hpp network/race_info_message.cpp \
network/remote_kart_info.hpp network/character_selected_message.hpp \
network/race_start_message.hpp \
network/race_start_message.hpp network/character_confirm_message.hpp \
network/connect_message.hpp network/connect_message.cpp \
network/num_players_message.hpp network/world_loaded_message.hpp \
network/connect_message.hpp network/character_info_message.hpp \
@ -86,8 +86,6 @@ supertuxkart_SOURCES = main.cpp \
shadow.cpp shadow.hpp \
particle_system.cpp particle_system.hpp \
game_manager.cpp game_manager.hpp \
widget_manager.cpp widget_manager.hpp \
widget.cpp widget.hpp \
camera.cpp camera.hpp \
sdldrv.cpp sdldrv.hpp \
moveable.cpp moveable.hpp \
@ -113,6 +111,8 @@ supertuxkart_SOURCES = main.cpp \
lisp/lexer.cpp lisp/lexer.hpp \
lisp/parser.cpp lisp/parser.hpp \
lisp/writer.cpp lisp/writer.hpp \
gui/widget_manager.cpp gui/widget_manager.hpp \
gui/widget.cpp gui/widget.hpp \
gui/menu_manager.cpp gui/menu_manager.hpp \
gui/base_gui.cpp gui/base_gui.hpp \
gui/race_gui.cpp gui/race_gui.hpp \

View File

@ -227,17 +227,13 @@ void CharSel::updateScrollPosition()
// set the 'selection changed' flag in the widget_manager, since update
// scroll position (when called on action up/down) will change the kart
// to display, even though it's the same widget
int current_widget = widget_manager->getSelectedWgt();
widget_manager->setSelectedWgt(current_widget+1);
widget_manager->setSelectedWgt(current_widget);
widget_manager->setSelectionChanged();
} // updateScrollPosition
//-----------------------------------------------------------------------------
void CharSel::switchGroup()
{
m_index_avail_karts.clear();
// This loop is too long (since getNumberOfKarts returns all karts in all groups),
// but the loop is left if no more kart is found.
const std::vector<int> &karts =
kart_properties_manager->getKartsInGroup(user_config->m_kart_group);
for(unsigned int i=0; i<karts.size(); i++)
@ -278,6 +274,23 @@ void CharSel::switchGroup()
} // switchGroup
//-----------------------------------------------------------------------------
/** This forces a re-display of the available characters. It is used from the
* network manager when a character confirm message is received from the
* server.
*/
void CharSel::updateAvailableCharacters()
{
// This call computes the available characters (even though in this case
// the group hasn't changed.
switchGroup();
// This re-displays the characters (even though the scroll position has
// not changed, one character might have been deleted).
updateScrollPosition();
} // updateAvailableCharacters
//-----------------------------------------------------------------------------
void CharSel::switchCharacter(int n)
{
int indx=m_index_avail_karts[n];
@ -306,6 +319,21 @@ void CharSel::update(float dt)
widget_manager->update(dt);
return;
}
// Are we still waiting for a confirmation?
if(network_manager->getState()==NetworkManager::NS_WAIT_FOR_KART_CONFIRMATION)
{
widget_manager->update(dt);
return;
}
// The selection was confirmed, proceed:
if(network_manager->getState()==NetworkManager::NS_KART_CONFIRMED)
{
nextMenu();
return;
}
static bool first=true;
if(first)
{
@ -372,6 +400,56 @@ void CharSel::update(float dt)
} // update
//----------------------------------------------------------------------------
/** Pushes the next menu onto the stack. In case of split screen that might
* be another instance of the character selection menu.
*/
void CharSel::nextMenu()
{
if(race_manager->getNumLocalPlayers() > 1 &&
menu_manager->isCurrentMenu(MENUID_CHARSEL_P1))
{
menu_manager->pushMenu(MENUID_CHARSEL_P2);
return;
}
if(race_manager->getNumLocalPlayers() > 2 &&
menu_manager->isCurrentMenu(MENUID_CHARSEL_P2))
{
menu_manager->pushMenu(MENUID_CHARSEL_P3);
return;
}
if (race_manager->getNumLocalPlayers() > 3 &&
menu_manager->isCurrentMenu(MENUID_CHARSEL_P3))
{
menu_manager->pushMenu(MENUID_CHARSEL_P4);
return;
}
// Last character selected
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
{
// Switch state to wait for race information
network_manager->waitForRaceInformation();
menu_manager->pushMenu(MENUID_START_RACE_FEEDBACK);
}
else
{
// The state of the server does not change now (so that it can keep
// on handling client selections). Waiting for all client infos
// happens in the start_race_feedback menu (which then triggers
// sending the race info).
if (race_manager->getMajorMode() == RaceManager::RM_GRAND_PRIX)
menu_manager->pushMenu(MENUID_GRANDPRIXSELECT);
else
menu_manager->pushMenu(MENUID_TRACKSEL);
}
} // nextMenu
// ----------------------------------------------------------------------------
/** Handles widget selection.
*/
void CharSel::select()
{
int wgt = widget_manager->getSelectedWgt();
@ -389,6 +467,9 @@ void CharSel::select()
updateScrollPosition();
return;
}
// Now it must be a character selection:
// -------------------------------------
int token = widget_manager->getSelectedWgt() - WTOK_RACER0;
if(token<0 || token>(int)m_index_avail_karts.size())
{
@ -409,61 +490,19 @@ void CharSel::select()
return;
}
const KartProperties* KP = kart_properties_manager->getKartById(kart_id);
if (KP != NULL)
{
race_manager->setLocalKartInfo(m_player_index, KP->getIdent());
user_config->m_player[m_player_index].setLastKartId(kart_id);
// Add selected kart (token) to selected karts vector so it cannot be
// selected again
kart_properties_manager->testAndSetKart(kart_id);
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
network_manager->sendCharacterSelected(m_player_index);
}
if (!KP) return;
if (race_manager->getNumLocalPlayers() > 1)
race_manager->setLocalKartInfo(m_player_index, KP->getIdent());
user_config->m_player[m_player_index].setLastKartId(kart_id);
// Send the confirmation message to all clients.
network_manager->sendCharacterSelected(m_player_index,
KP->getIdent());
// In non-network more or on the server add selected kart (token) to
// selected karts vector so it cannot be selected again
if(network_manager->getMode()!=NetworkManager::NW_CLIENT)
{
if (menu_manager->isCurrentMenu(MENUID_CHARSEL_P1))
{
menu_manager->pushMenu(MENUID_CHARSEL_P2);
return;
}
}
if (race_manager->getNumLocalPlayers() > 2)
{
if (menu_manager->isCurrentMenu(MENUID_CHARSEL_P2))
{
menu_manager->pushMenu(MENUID_CHARSEL_P3);
return;
}
}
if (race_manager->getNumLocalPlayers() > 3)
{
if (menu_manager->isCurrentMenu(MENUID_CHARSEL_P3))
{
menu_manager->pushMenu(MENUID_CHARSEL_P4);
return;
}
}
// Last character selected"
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
{
// Switch state to wait for race information
network_manager->waitForRaceInformation();
menu_manager->pushMenu(MENUID_START_RACE_FEEDBACK);
}
else
{
// The state of the server does not change now (so that it can keep
// on handling client selections). Waiting for all client infos
// happens in the start_race_feedback menu (which then triggers
// sending the race info).
if (race_manager->getMajorMode() == RaceManager::RM_GRAND_PRIX)
menu_manager->pushMenu(MENUID_GRANDPRIXSELECT);
else
menu_manager->pushMenu(MENUID_TRACKSEL);
kart_properties_manager->selectKart(kart_id);
nextMenu();
}
} // select

View File

@ -41,13 +41,15 @@ private:
void updateScrollPosition();
int computeIndent(int n) {return 40+abs((int)(m_max_entries-1)/2 - n)*3;}
void switchGroup();
void nextMenu();
void switchCharacter(int n);
public:
CharSel(int which_player);
~CharSel();
CharSel(int which_player);
~CharSel();
void switchCharacter(int n);
void update(float dt);
void select();
void update(float dt);
void select();
void updateAvailableCharacters();
virtual void handle(GameAction, int);
};

View File

@ -28,6 +28,7 @@ enum WidgetTokens
WTOK_MSG
};
/** Constructor for feedback screen. */
StartRaceFeedback::StartRaceFeedback()
{
m_is_first_frame = true;
@ -45,16 +46,21 @@ StartRaceFeedback::StartRaceFeedback()
}
widget_manager->layout(WGT_AREA_ALL);
}
} // StartRaceFeedback
//-----------------------------------------------------------------------------
/** Destructor for feedback screen.
*/
StartRaceFeedback::~StartRaceFeedback()
{
widget_manager->reset();
}
} // ~StartRaceFeedback
//-----------------------------------------------------------------------------
/** Updates the feedback screen. Depending on the state of the network manager
* it will change the displayed text.
* \param delta Time step size.
*/
void StartRaceFeedback::update(float delta)
{
// First test if we are still waiting

View File

@ -20,9 +20,18 @@
#include "base_gui.hpp"
/** This class is used to give feedback to the user while loading the track.
* It either displays a 'Loading track' or a 'Wait for synchronisation'
* message (dependent on the stage of the race manager).
*/
class StartRaceFeedback: public BaseGUI
{
protected:
/** Flag used to make sure that the text is actually displayed (i.e
* update was called once) before loading the track - otherwise the
* text is set in the widget, but not on the screen since the screen
* wasn't updated.
*/
bool m_is_first_frame;
public:
StartRaceFeedback();

View File

@ -200,9 +200,12 @@ public:
int getSelectedWgt() const { return m_selected_wgt_token; }
void setSelectedWgt(const int TOKEN);
//Checks if the selected widget changed since the last call to update()
/** Checks if the selected widget changed since the last call to update() */
bool selectionChanged() const { return m_selection_change; }
/** Forces the changed selection mode. */
void setSelectionChanged() { m_selection_change = true; }
/* Macro functions. They are widgets with special predefined values. */
//FIXME: Temporal, till I rename addWgt() to addEmptyWgt()

View File

@ -106,7 +106,7 @@
Optimization="2"
EnableIntrinsicFunctions="true"
WholeProgramOptimization="false"
AdditionalIncludeDirectories="C:\cygwin\home\joerg\nw\src\enet\include"
AdditionalIncludeDirectories="../../enet/include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"

View File

@ -915,14 +915,6 @@
RelativePath="..\..\vec3.cpp"
>
</File>
<File
RelativePath="..\..\widget.cpp"
>
</File>
<File
RelativePath="..\..\widget_manager.cpp"
>
</File>
<File
RelativePath="../../../src\world.cpp"
>
@ -1042,6 +1034,14 @@
RelativePath="../../../src\gui\track_sel.cpp"
>
</File>
<File
RelativePath="..\..\gui\widget.cpp"
>
</File>
<File
RelativePath="..\..\gui\widget_manager.cpp"
>
</File>
</Filter>
<Filter
Name="lisp"
@ -1437,14 +1437,6 @@
RelativePath="..\..\vec3.hpp"
>
</File>
<File
RelativePath="..\..\widget.hpp"
>
</File>
<File
RelativePath="..\..\widget_manager.hpp"
>
</File>
<File
RelativePath="../../../src\world.hpp"
>
@ -1564,6 +1556,14 @@
RelativePath="../../../src\gui\track_sel.hpp"
>
</File>
<File
RelativePath="..\..\widget.hpp"
>
</File>
<File
RelativePath="..\..\widget_manager.hpp"
>
</File>
</Filter>
<Filter
Name="lisp"
@ -1608,6 +1608,10 @@
<Filter
Name="network"
>
<File
RelativePath="..\..\network\character_confirm_message.hpp"
>
</File>
<File
RelativePath="..\..\network\character_info_message.hpp"
>

View File

@ -224,6 +224,16 @@ bool KartPropertiesManager::kartAvailable(int kartid)
return true;
} // testAndSetKart
//-----------------------------------------------------------------------------
/** Sets a kart to be selected by specifying the identifier (name) of the kart.
* \param kart_name Name of the kart.
*/
void KartPropertiesManager::selectKartName(const std::string &kart_name)
{
int kart_id = getKartId(kart_name);
selectKart(kart_id);
} // selectKartName
//-----------------------------------------------------------------------------
/** Returns a list of randomly selected karts. This list firstly contains
* karts in the currently selected group, but which are not in the list

View File

@ -66,6 +66,9 @@ public:
bool kartAvailable(int kartid);
std::vector<std::string> getAllAvailableKarts() const;
void setUnavailableKarts(std::vector<std::string>);
/** Sets a kartid to be selected (without any tests). */
void selectKart(int kartid) {m_selected_karts.push_back(kartid);}
void selectKartName(const std::string &kart_name);
bool testAndSetKart(int kartid);
std::vector<std::string> getRandomKartList(int count, RemoteKartInfoList& existing_karts);
void removeTextures ();

View File

@ -55,7 +55,7 @@
#include "file_manager.hpp"
#include "loader.hpp"
#include "game_manager.hpp"
#include "widget_manager.hpp"
#include "gui/widget_manager.hpp"
#include "material_manager.hpp"
#include "sdldrv.hpp"
#include "callback_manager.hpp"

View File

@ -0,0 +1,72 @@
// $Id: character_confirm_message.hpp 2128 2008-06-13 00:53:52Z cosmosninja $
//
// 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_CHARACTER_CONFIRM_MESSAGE_HPP
#define HEADER_CHARACTER_CONFIRM_MESSAGE_HPP
#include <string>
#include "network/message.hpp"
/** This message is from the server to all clients to inform them about a
* newly selected character. This means that this character is not available
* anymore. The message contains the hostid of the client who selected this
* character (0 in case of server), so that this message acts as a
* confirmation for the corresponding client (or a reject if the message has
* a different hostid, meaning that another client selected the character
* earlier).
*/
class CharacterConfirmMessage : public Message
{
private:
/** The host id. */
int m_host_id;
/** Name of the selected kart. */
std::string m_kart_name;
public:
/** Constructor, takes the name of the kart name and the host id.
* \param kart_name Name of the kart.
* \param host_id Id of the host who selected this character.
*/
CharacterConfirmMessage(const std::string &kart_name, int host_id)
: Message(Message::MT_CHARACTER_CONFIRM)
{
allocate(getStringLength(kart_name) + getCharLength());
addString(kart_name);
addChar(host_id);
} // CharacterConfirmMessage
// ------------------------------------------------------------------------
/** Unpacks a character confirm message.
* \param pkt Received enet packet.
*/
CharacterConfirmMessage(ENetPacket* pkt):Message(pkt, MT_CHARACTER_CONFIRM)
{
m_kart_name = getString();
m_host_id = getChar();
} // CharacterConfirmMessage(EnetPacket)
// ------------------------------------------------------------------------
/** Returns the kart name contained in a received message. */
const std::string &getKartName() const { return m_kart_name; }
/** Returns the host id contained in a received message. */
int getHostId() const { return m_host_id; }
}; // CharacterConfirmMessage
#endif

View File

@ -21,18 +21,42 @@
#define HEADER_CHARACTER_SELECTED_MESSAGE_H
#include "network/message.hpp"
#include "user_config.hpp"
#include "race_manager.hpp"
#include "network/remote_kart_info.hpp"
/** This message is send contains information about selected karts. It is send
* from the client to the server to indicate a selected kart, and from the
* server to the clients to indicate that a kart was selected. In the latter
* case it contains the hostid of the successful selecter. This way a client
* selecting a kart can check if its selection was successful or not, and
* other clients are informed that a certain kart is not available anymore.
*/
class CharacterSelectedMessage : public Message
{
private:
/** Number of local players on a host. If the message is send from the
* server to the clients, this field instead contains the host id of
* the host which selected the kart
*/
int m_num_local_players;
/** Stores information about the selected kart. */
RemoteKartInfo m_kart_info;
// For now this is an empty message
public:
CharacterSelectedMessage(int player_id) :Message(Message::MT_CHARACTER_INFO)
/** Contains information about a selected kart. When send from the client
* to the server, it contains the number of local players (which
* technically needs only to be sent once); when send from from the server
* to the clients this field instead contains the host id of the host
* selected the character. This allows the client to detect if a selected
* kart was not confirmed by the server (i.e. another client or the server
* has selected the kart first
* \param player_id The local player id.
* \param host_id If this value is specified (>-1), then this value is
* used in the message instead of the number of local
* players.
*/
CharacterSelectedMessage(int player_id, int host_id=-1)
: Message(Message::MT_CHARACTER_INFO)
{
m_kart_info = race_manager->getLocalKartInfo(player_id);
m_num_local_players = race_manager->getNumLocalPlayers();
@ -46,9 +70,18 @@ public:
addString(m_kart_info.getPlayerName());
// Piggy backing this information saves sending it as a separate
// message. It is actually only required in the first message
addChar(race_manager->getNumLocalPlayers());
if(host_id>-1)
addChar(host_id);
else
addChar(race_manager->getNumLocalPlayers());
} // CharacterSelectedMessage
// ------------------------------------------------------------------------
/** Unpacks a character selected message. The additional field is either
* the number of local players (when send from client to server), or the
* hostid of the host selected the character.
* \param pkt Received enet packet.
*/
CharacterSelectedMessage(ENetPacket* pkt):Message(pkt, MT_CHARACTER_INFO)
{
m_kart_info.setLocalPlayerId(getChar());
@ -56,8 +89,18 @@ public:
m_kart_info.setPlayerName(getString());
m_num_local_players = getChar();
} // CharacterSelectedMessage(EnetPacket)
// ------------------------------------------------------------------------
/** Returns the remote kart info structure of the selected kart. */
const RemoteKartInfo& getKartInfo () const { return m_kart_info; }
/** Returns the number of local players. */
int getNumPlayers() const { return m_num_local_players; }
/** Returns the host id of the host who selected the kart successfully.
* This information is actually stored in m_num_local_players field, which
* is used when a client receives this message.
*/
int getHostId () const { return m_num_local_players; }
}; // CharacterSelectedMessage
#endif

View File

@ -43,9 +43,9 @@
class Message
{
public:
enum MessageType {MT_CONNECT=1, MT_CHARACTER_INFO,
enum MessageType {MT_CONNECT=1, MT_CHARACTER_INFO, MT_CHARACTER_CONFIRM,
MT_RACE_INFO, MT_RACE_START, MT_WORLD_LOADED,
MT_KART_INFO, MT_KART_CONTROL,
MT_KART_INFO, MT_KART_CONTROL,
MT_RACE_STATE};
private:
ENetPacket *m_pkt;

View File

@ -26,12 +26,14 @@
#include "network/world_loaded_message.hpp"
#include "network/race_state.hpp"
#include "network/kart_control_message.hpp"
#include "network/character_confirm_message.hpp"
#include "stk_config.hpp"
#include "user_config.hpp"
#include "race_manager.hpp"
#include "kart_properties_manager.hpp"
#include "translation.hpp"
#include "gui/font.hpp"
#include "gui/menu_manager.hpp"
#include "gui/char_sel.hpp"
NetworkManager* network_manager = 0;
@ -220,6 +222,7 @@ void NetworkManager::handleMessageAtServer(ENetEvent *event)
m_num_clients++;
return;
}
case NS_KART_CONFIRMED: // Fall through
case NS_CHARACTER_SELECT:
{
CharacterSelectedMessage m(event->packet);
@ -235,12 +238,22 @@ void NetworkManager::handleMessageAtServer(ENetEvent *event)
RemoteKartInfo ki=m.getKartInfo();
ki.setHostId(hostid);
m_kart_info.push_back(ki);
int kart_id = kart_properties_manager->getKartId(ki.getKartName());
kart_properties_manager->testAndSetKart(kart_id);
CharSel *menu = dynamic_cast<CharSel*>(menu_manager->getCurrentMenu());
if(menu)
menu->updateAvailableCharacters();
// Broadcast the information about a selected kart to all clients
CharacterConfirmMessage ccm(ki.getKartName(), hostid);
broadcastToClients(ccm);
// See if this was the last message, i.e. we have received at least
// one message from each client, and the size of the kart_info
// array is the same as the number of all players (which does not
// yet include the number of players on the host).
if(m_barrier_count == (int)m_num_clients &&
m_num_all_players==(int)m_kart_info.size())
m_num_all_players==(int)m_kart_info.size())
{
// we can't send the race info yet, since the server might
// not yet have selected all characters!
@ -275,8 +288,47 @@ void NetworkManager::handleMessageAtClient(ENetEvent *event)
m_state = NS_CHARACTER_SELECT;
break;
}
case NS_CHARACTER_SELECT:
{
CharacterConfirmMessage m(event->packet);
kart_properties_manager->selectKartName(m.getKartName());
CharSel *menu = dynamic_cast<CharSel*>(menu_manager->getCurrentMenu());
if(menu)
menu->updateAvailableCharacters();
break;
}
case NS_WAIT_FOR_KART_CONFIRMATION:
{
CharacterConfirmMessage m(event->packet);
kart_properties_manager->selectKartName(m.getKartName());
// If the current menu is the character selection menu,
// update the menu so that the newly taken character is removed.
CharSel *menu = dynamic_cast<CharSel*>(menu_manager->getCurrentMenu());
if(menu)
menu->updateAvailableCharacters();
// Check if we received a message about the kart we just selected.
// If so, the menu needs to progress, otherwise a different kart
// must be selected by the current player.
if(m.getKartName()==m_kart_to_confirm)
{
int host_id = m.getHostId();
m_state = (host_id == getMyHostId()) ? NS_KART_CONFIRMED
: NS_CHARACTER_SELECT;
} // m.getkartName()==m_kart_to_confirm
break;
} // wait for kart confirmation
case NS_WAIT_FOR_RACE_DATA:
{
// It is possible that character confirm messages arrive at the
// client when it has already left the character selection screen.
// In this case the messages can simply be ignored.
if(Message::peekType(event->packet)==Message::MT_CHARACTER_CONFIRM)
{
// Receiving it will automatically free the memory.
CharacterConfirmMessage m(event->packet);
return;
}
RaceInfoMessage m(event->packet);
// The constructor actually sets the information in the race manager
m_state = NS_LOADING_WORLD;
@ -391,10 +443,28 @@ void NetworkManager::switchToCharacterSelection()
} // switchTocharacterSelection
// ----------------------------------------------------------------------------
void NetworkManager::sendCharacterSelected(int player_id)
/** Called on the client to send the data about the selected kart to the
* server and wait for confirmation.
* \param player_id Local id of the player which selected the kart.
* \param kart_id Identifier of the selected kart. this is used to wait till
* a message about this kart is received back from the server.
*/
void NetworkManager::sendCharacterSelected(int player_id,
const std::string &kart_id)
{
CharacterSelectedMessage m(player_id);
sendToServer(m);
if(m_mode==NW_SERVER)
{
CharacterConfirmMessage ccm(kart_id, getMyHostId());
broadcastToClients(ccm);
}
else if(m_mode==NW_CLIENT)
{
CharacterSelectedMessage m(player_id);
sendToServer(m);
// Wait till we receive confirmation about the selected character.
m_state = NS_WAIT_FOR_KART_CONFIRMATION;
m_kart_to_confirm = kart_id;
}
} // sendCharacterSelected
// ----------------------------------------------------------------------------

View File

@ -41,6 +41,9 @@ public:
NS_ACCEPT_CONNECTIONS, // server: accept connections
NS_WAIT_FOR_AVAILABLE_CHARACTERS, // client: wait for list
NS_ALL_REMOTE_CHARACTERS_DONE, // server: all client data received
NS_WAIT_FOR_KART_CONFIRMATION, // client: wait for confirmation
// if character selection was ok
NS_KART_CONFIRMED, // Character was confirmed
NS_WAIT_FOR_RACE_DATA, // client: wait for race info
NS_READY_SET_GO_BARRIER, // c&s: barrier before r.s.g.
NS_CHARACTER_SELECT, // c&s: character select in progress
@ -62,6 +65,8 @@ private:
ENetHost *m_host; // me
ENetPeer *m_server; // (clients only)
std::vector<ENetPeer*> m_clients; // (server only) pos in vector is client host_id
/** Name of the kart that a client is waiting for confirmation for. */
std::string m_kart_to_confirm;
bool initServer();
bool initClient();
@ -78,15 +83,15 @@ private:
public:
NetworkManager();
~NetworkManager();
void setMode(NetworkMode m) {m_mode = m; }
NetworkMode getMode() const {return m_mode; }
void setMode(NetworkMode m) {m_mode = m; }
NetworkMode getMode() const {return m_mode; }
void becomeServer();
void becomeClient();
void setState(NetworkState s) {m_state = s; }
NetworkState getState() const {return m_state; }
int getMyHostId() const {return m_host_id; }
void setHostId(int host_id) {m_host_id = host_id; }
unsigned int getNumClients() const {return m_num_clients; }
void setState(NetworkState s) {m_state = s; }
NetworkState getState() const {return m_state; }
int getMyHostId() const {return m_host_id; }
void setHostId(int host_id) {m_host_id = host_id; }
unsigned int getNumClients() const {return m_num_clients; }
const std::string&
getClientName(int i) const {return m_client_names[i];}
bool initialiseConnections();
@ -95,7 +100,7 @@ public:
void disableNetworking();
void sendConnectMessage(); // client send initial info to server
void switchToCharacterSelection();
void sendCharacterSelected(int player_id);
void sendCharacterSelected(int player_id, const std::string &kartid);
void waitForRaceInformation();
void worldLoaded();
void setupPlayerKartInfo();
@ -108,4 +113,3 @@ public:
extern NetworkManager *network_manager;
#endif

View File

@ -17,12 +17,13 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "race_manager.hpp"
#include <iostream>
#include "track_manager.hpp"
#include "game_manager.hpp"
#include "kart_properties_manager.hpp"
#include "race_manager.hpp"
#include "unlock_manager.hpp"
#include "gui/menu_manager.hpp"
#include "world.hpp"
@ -58,13 +59,12 @@ RaceManager::~RaceManager()
} // ~RaceManager
//-----------------------------------------------------------------------------
/** Resets the race manager.
/** Resets the race manager. It is called by world when restarting a race.
*/
void RaceManager::reset()
{
m_num_finished_karts = 0;
m_num_finished_players = 0;
m_player_karts.clear();
} // reset
//-----------------------------------------------------------------------------

View File

@ -82,6 +82,7 @@ private:
Difficulty m_difficulty;
RaceModeType m_major_mode, m_minor_mode;
typedef std::vector<std::string> PlayerKarts;
/** Stores remote kart information about all player karts. */
std::vector<RemoteKartInfo> m_player_karts;
std::vector<RemoteKartInfo> m_local_kart_info;
std::vector<std::string> m_tracks;

View File

@ -38,7 +38,7 @@
#include "projectile_manager.hpp"
#include "loader.hpp"
#include "gui/menu_manager.hpp"
#include "widget_manager.hpp"
#include "gui/widget_manager.hpp"
#include "player.hpp"
#include "gui/font.hpp"
#include "user_config.hpp"

View File

@ -79,28 +79,28 @@ UnlockManager::UnlockManager()
// Load challenges from .../data/karts
// -----------------------------------
file_manager->listFiles(dirs, file_manager->getKartDir(),
/*is_full_path*/ true);
// Find out which characters are available and load them
for(std::set<std::string>::iterator i = dirs.begin();
i != dirs.end(); i++)
{
std::string challenge_file;
try
{
challenge_file = file_manager->getKartFile((*i)+".challenge");
}
catch (std::exception& e)
{
(void)e; // remove warning about unused variable
continue;
}
FILE *f=fopen(challenge_file.c_str(),"r");
if(!f) continue;
fclose(f);
addChallenge(new ChallengeData(challenge_file));
} // for i
file_manager->listFiles(dirs, file_manager->getKartDir(),
/*is_full_path*/ true);
// Find out which characters are available and load them
for(std::set<std::string>::iterator i = dirs.begin();
i != dirs.end(); i++)
{
std::string challenge_file;
try
{
challenge_file = file_manager->getKartFile((*i)+".challenge");
}
catch (std::exception& e)
{
(void)e; // remove warning about unused variable
continue;
}
FILE *f=fopen(challenge_file.c_str(),"r");
if(!f) continue;
fclose(f);
addChallenge(new ChallengeData(challenge_file));
} // for i
// Challenges from .../data/grandprix
// ----------------------------------