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:
parent
7203ad76c9
commit
8a4a939980
@ -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 \
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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()
|
@ -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"
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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
|
||||
|
@ -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 ();
|
||||
|
@ -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"
|
||||
|
72
src/network/character_confirm_message.hpp
Executable file
72
src/network/character_confirm_message.hpp
Executable 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
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
// ----------------------------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user