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
This commit is contained in:
hikerstk 2008-09-09 04:20:24 +00:00
parent 46b44f202e
commit e4c646c0c5
4 changed files with 99 additions and 32 deletions

View File

@ -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<std::string> KartPropertiesManager::getAllAvailableKarts() const
{
std::vector<std::string> 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<std::string> 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<int>::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<std::string> KartPropertiesManager::getRandomKartList(int count,
RemoteKartInfoList& existing_karts)
RemoteKartInfoList& existing_karts)
{
std::vector<std::string> random_karts;
@ -205,10 +256,11 @@ std::vector<std::string> KartPropertiesManager::getRandomKartList(int count,
// --------------------------------
std::vector<int> karts = getKartsInGroup(user_config->m_kart_group);
std::vector<int>::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<karts.size();)
{
if(used[karts[i]])
if(used[karts[i]] || !m_kart_available[karts[i]])
karts.erase(karts.begin()+i);
else
i++;
@ -233,7 +285,7 @@ std::vector<std::string> KartPropertiesManager::getRandomKartList(int count,
karts.clear();
for(unsigned int i=0; i<getNumberOfKarts(); i++)
{
if(!used[i]) karts.push_back(i);
if(!used[i] && m_kart_available[i]) karts.push_back(i);
}
std::random_shuffle(karts.begin(), karts.end());
// Then fill up the remaining empty spaces

View File

@ -29,12 +29,15 @@ class KartProperties;
class KartPropertiesManager
{
private:
std::vector<std::string> m_all_groups;
std::vector<std::string> m_all_groups;
std::map<std::string, std::vector<int> > 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.
/** 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<int> m_selected_karts;
/** Contains a flag for each kart indicating wether it is available on
* all clients or not. */
std::vector<bool> 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<int>& 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<std::string>
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<std::string> getAllAvailableKarts() const;
void setUnavailableKarts(std::vector<std::string>);
bool testAndSetKart(int kartid);
std::vector<std::string> getRandomKartList(int count, RemoteKartInfoList& existing_karts);
void removeTextures ();
};
extern KartPropertiesManager *kart_properties_manager;

View File

@ -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);

View File

@ -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<std::string> &all_tracks =
track_manager->getAllTrackIdentifiers();
allocate(getStringLength(m_id) + getStringVectorLength(all_tracks));
track_manager->getAllTrackIdentifiers();
std::vector<std::string> 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<std::string> all_tracks = getStringVector();
std::vector<std::string> all_karts = getStringVector();
track_manager->setUnavailableTracks(all_tracks);
kart_properties_manager->setUnavailableKarts(all_karts);
} // ConnectMessage
// ----------------------------------------------------------------------------