From e4c646c0c5ddc928e5a2e5ab3a24c7fff718a8f0 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 9 Sep 2008 04:20:24 +0000 Subject: [PATCH] Make sure that only karts available on all clients can be selected. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2255 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/kart_properties_manager.cpp | 80 +++++++++++++++++++++----- src/kart_properties_manager.hpp | 34 ++++++----- src/network/character_info_message.hpp | 5 +- src/network/connect_message.cpp | 12 +++- 4 files changed, 99 insertions(+), 32 deletions(-) diff --git a/src/kart_properties_manager.cpp b/src/kart_properties_manager.cpp index a562d63df..f5a091f07 100644 --- a/src/kart_properties_manager.cpp +++ b/src/kart_properties_manager.cpp @@ -87,6 +87,7 @@ void KartPropertiesManager::loadKartData(bool dont_load_models) KartProperties* kp = new KartProperties(); kp->load(kart_file, "tuxkart-kart", dont_load_models); m_karts_properties.push_back(kp); + m_kart_available.push_back(true); if(kp->getMaxSteerAngle(0) > m_max_steer_angle) { m_max_steer_angle = kp->getMaxSteerAngle(0); @@ -104,30 +105,28 @@ void KartPropertiesManager::loadKartData(bool dont_load_models) } // loadKartData //----------------------------------------------------------------------------- -const int KartPropertiesManager::getKartId(const std::string IDENT) const +const int KartPropertiesManager::getKartId(const std::string &ident) const { - int j = 0; for(KartPropertiesVector::const_iterator i = m_karts_properties.begin(); i != m_karts_properties.end(); ++i) { - if ((*i)->getIdent() == IDENT) - return j; - ++j; + if ((*i)->getIdent() == ident) + return i-m_karts_properties.begin(); } char msg[MAX_ERROR_MESSAGE_LENGTH]; snprintf(msg, sizeof(msg), "KartPropertiesManager: Couldn't find kart: '%s'", - IDENT.c_str()); + ident.c_str()); throw std::runtime_error(msg); } // getKartId //----------------------------------------------------------------------------- -const KartProperties* KartPropertiesManager::getKart(const std::string IDENT) const +const KartProperties* KartPropertiesManager::getKart(const std::string &ident) const { for(KartPropertiesVector::const_iterator i = m_karts_properties.begin(); i != m_karts_properties.end(); ++i) { - if ((*i)->getIdent() == IDENT) + if ((*i)->getIdent() == ident) return *i; } @@ -141,11 +140,49 @@ const KartProperties* KartPropertiesManager::getKartById(int i) const return NULL; return m_karts_properties[i]; -} +} // getKartById +//----------------------------------------------------------------------------- +/** Returns a list of all available kart identifiers. */ +std::vector KartPropertiesManager::getAllAvailableKarts() const +{ + std::vector all; + for(KartPropertiesVector::const_iterator i = m_karts_properties.begin(); + i != m_karts_properties.end(); ++i) + { + if(m_kart_available[i-m_karts_properties.begin()]) + all.push_back((*i)->getIdent()); + } + return all; +} // getAllAvailableKarts + +//----------------------------------------------------------------------------- +/** Marks all karts except the ones listed in the string vector to be + * unavailable. This function is used on a client when receiving the list of + * karts from a client to mark all other karts as unavailable. + * \param karts List of karts that are available on a client. + */ +void KartPropertiesManager::setUnavailableKarts(std::vector karts) +{ + for(KartPropertiesVector::const_iterator i = m_karts_properties.begin(); + i != m_karts_properties.end(); ++i) + { + if(!m_kart_available[i-m_karts_properties.begin()]) continue; + + if(std::find(karts.begin(), karts.end(), (*i)->getIdent()) + == karts.end()) + { + m_kart_available[i-m_karts_properties.begin()]=false; + fprintf(stderr, "Kart '%s' not available on all clients, disabled.\n", + (*i)->getIdent().c_str()); + + } // kart not in list + } // for i in m_kart_properties + +} // setUnavailableKarts //----------------------------------------------------------------------------- /** Returns the (global) index of the n-th kart of a given group. If there is - * no such kart, -1 is returned + * no such kart, -1 is returned. */ int KartPropertiesManager::getKartByGroup(const std::string& group, int n) const { @@ -170,8 +207,13 @@ bool KartPropertiesManager::testAndSetKart(int kartid) } // testAndSetKart //----------------------------------------------------------------------------- +/** Returns true if a kart is available to be selected. A kart is available to + * be selected if it is available on all clients (i.e. m_kart_available is + * true), not yet selected, and not locked. + */ bool KartPropertiesManager::kartAvailable(int kartid) { + if(!m_kart_available[kartid]) return false; std::vector::iterator it; for (it = m_selected_karts.begin(); it < m_selected_karts.end(); it++) { @@ -183,8 +225,17 @@ bool KartPropertiesManager::kartAvailable(int kartid) } // testAndSetKart //----------------------------------------------------------------------------- +/** Returns a list of randomly selected karts. This list firstly contains + * karts in the currently selected group, but which are not in the list + * of 'existing karts'. If not enough karts are available in the current + * group, karts from all other groups are used to fill up the list. + * This is used by the race manager to select the AI karts. + * \param count Number of karts to select randomly. + * \param existing_karst List of karts that should not be used. This is the + * list of karts selected by the players. + */ std::vector KartPropertiesManager::getRandomKartList(int count, - RemoteKartInfoList& existing_karts) + RemoteKartInfoList& existing_karts) { std::vector random_karts; @@ -205,10 +256,11 @@ std::vector KartPropertiesManager::getRandomKartList(int count, // -------------------------------- std::vector karts = getKartsInGroup(user_config->m_kart_group); std::vector::iterator k; - // Remove karts that are already used + // Remove karts that are already used or generally not available + // (i.e. locked or not available on all clients) for(unsigned int i=0; i KartPropertiesManager::getRandomKartList(int count, karts.clear(); for(unsigned int i=0; i m_all_groups; + std::vector m_all_groups; std::map > m_groups; - // vector containing kart numbers that have been selected in multiplayer - // games. This it used to ensure the same kart can not be selected more - // than once. - std::vector m_selected_karts; + /** Vector containing kart numbers that have been selected in multiplayer + * games. This it used to ensure the same kart can not be selected more + * than once. */ + std::vector m_selected_karts; + /** Contains a flag for each kart indicating wether it is available on + * all clients or not. */ + std::vector m_kart_available; protected: float m_max_steer_angle; @@ -47,8 +50,8 @@ public: ~KartPropertiesManager(); const KartProperties* getKartById (int i) const; - const KartProperties* getKart (const std::string IDENT) const; - const int getKartId (const std::string IDENT) const; + const KartProperties* getKart (const std::string &ident) const; + const int getKartId (const std::string &ident) const; int getKartByGroup (const std::string& group, int i) const; void loadKartData (bool dont_load_models=false); const float getMaximumSteeringAngle() const {return m_max_steer_angle;} @@ -57,14 +60,15 @@ public: getAllGroups () const {return m_all_groups; } const std::vector& getKartsInGroup (const std::string& g) {return m_groups[g]; } - void clearAllSelectedKarts() {m_selected_karts.clear();} - void removeLastSelectedKart() {m_selected_karts.pop_back();} - int getNumSelectedKarts() const {return m_selected_karts.size();} - bool kartAvailable(int kartid); - bool testAndSetKart(int kartid); - std::vector - getRandomKartList(int count, RemoteKartInfoList& existing_karts); - void removeTextures (); + void clearAllSelectedKarts() {m_selected_karts.clear();} + void removeLastSelectedKart() {m_selected_karts.pop_back();} + int getNumSelectedKarts() const {return m_selected_karts.size();} + bool kartAvailable(int kartid); + std::vector getAllAvailableKarts() const; + void setUnavailableKarts(std::vector); + bool testAndSetKart(int kartid); + std::vector getRandomKartList(int count, RemoteKartInfoList& existing_karts); + void removeTextures (); }; extern KartPropertiesManager *kart_properties_manager; diff --git a/src/network/character_info_message.hpp b/src/network/character_info_message.hpp index 220465e5e..d1870ebbf 100644 --- a/src/network/character_info_message.hpp +++ b/src/network/character_info_message.hpp @@ -22,11 +22,14 @@ #include "network/message.hpp" +/** This message is sent from the server to the clients and contains the list + * of available characters. Additionally, it contains the clients id. + */ class CharacterInfoMessage : public Message { // Add the remote host id to this message (to avoid sending this separately) public: - CharacterInfoMessage(int hostid) :Message(Message::MT_CHARACTER_INFO) + CharacterInfoMessage(int hostid) : Message(Message::MT_CHARACTER_INFO) { allocate(getCharLength()); addChar(hostid); diff --git a/src/network/connect_message.cpp b/src/network/connect_message.cpp index 759edf88e..01eef41d3 100755 --- a/src/network/connect_message.cpp +++ b/src/network/connect_message.cpp @@ -28,6 +28,7 @@ #include "user_config.hpp" #include "track_manager.hpp" +#include "kart_properties_manager.hpp" // ---------------------------------------------------------------------------- /** Creates the connect message. It includes the id of the client (currently @@ -37,10 +38,15 @@ ConnectMessage::ConnectMessage() : Message(MT_CONNECT) { setId(); const std::vector &all_tracks = - track_manager->getAllTrackIdentifiers(); - allocate(getStringLength(m_id) + getStringVectorLength(all_tracks)); + track_manager->getAllTrackIdentifiers(); + std::vector all_karts = + kart_properties_manager->getAllAvailableKarts(); + all_karts.erase(all_karts.begin()); + allocate(getStringLength(m_id) + getStringVectorLength(all_tracks) + + getStringVectorLength(all_karts)); addString(m_id); addStringVector(all_tracks); + addStringVector(all_karts); } // ConnectMessage // ---------------------------------------------------------------------------- @@ -53,7 +59,9 @@ ConnectMessage::ConnectMessage(ENetPacket* pkt):Message(pkt, MT_CONNECT) { m_id = getString(); std::vector all_tracks = getStringVector(); + std::vector all_karts = getStringVector(); track_manager->setUnavailableTracks(all_tracks); + kart_properties_manager->setUnavailableKarts(all_karts); } // ConnectMessage // ----------------------------------------------------------------------------