~ubuntu-branches/ubuntu/precise/supertuxkart/precise

« back to all changes in this revision

Viewing changes to src/karts/kart_properties_manager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger
  • Date: 2011-02-24 22:36:25 UTC
  • mfrom: (1.1.9 upstream) (6.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20110224223625-ygrjfpg92obovuch
Tags: 0.7+dfsg1-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//  $Id: kart_properties_manager.cpp 3147 2009-02-16 00:29:03Z hikerstk $
 
1
//  $Id: kart_properties_manager.cpp 7101 2010-12-20 02:13:39Z auria $
2
2
//
3
3
//  SuperTuxKart - a fun racing game with go-kart
4
4
//  Copyright (C) 2004-2006 Ingo Ruhnke <grumbel@gmx.de>
19
19
 
20
20
#include "karts/kart_properties_manager.hpp"
21
21
 
22
 
#include <stdexcept>
23
22
#include <algorithm>
24
23
#include <ctime>
 
24
#include <stdio.h>
 
25
#include <stdexcept>
25
26
 
26
 
#include "file_manager.hpp"
27
 
#include "stk_config.hpp"
28
 
#include "user_config.hpp"
29
27
#include "challenges/unlock_manager.hpp"
 
28
#include "config/stk_config.hpp"
 
29
#include "config/user_config.hpp"
 
30
#include "graphics/irr_driver.hpp"
 
31
#include "guiengine/engine.hpp"
 
32
#include "io/file_manager.hpp"
30
33
#include "karts/kart_properties.hpp"
31
34
#include "utils/string_utils.hpp"
32
35
 
33
36
KartPropertiesManager *kart_properties_manager=0;
34
37
 
 
38
std::vector<std::string> KartPropertiesManager::m_kart_search_path;
 
39
 
 
40
/** Constructor, only clears internal data structures. */
35
41
KartPropertiesManager::KartPropertiesManager()
36
42
{
37
43
    m_all_groups.clear();
38
44
}   // KartPropertiesManager
39
45
 
40
46
//-----------------------------------------------------------------------------
 
47
/** Destructor. Removes all allocated data.
 
48
 */
41
49
KartPropertiesManager::~KartPropertiesManager()
42
50
{
43
51
    for(KartPropertiesVector::iterator i  = m_karts_properties.begin();
51
59
}   // ~KartPropertiesManager
52
60
 
53
61
//-----------------------------------------------------------------------------
54
 
void KartPropertiesManager::removeTextures()
 
62
/** Adds a directory from which karts are loaded. The kart manager checks if
 
63
 *  either this directory itself contains a kart, and if any subdirectory 
 
64
 *  contains a kart.
 
65
 *  \param dir The directory to add. 
 
66
 */
 
67
void KartPropertiesManager::addKartSearchDir(const std::string &s)
 
68
{
 
69
    m_kart_search_path.push_back(s);
 
70
}   // addKartSearchDir
 
71
 
 
72
//-----------------------------------------------------------------------------
 
73
void KartPropertiesManager::unloadAllKarts()
55
74
{
56
75
    for(KartPropertiesVector::iterator i  = m_karts_properties.begin();
57
76
        i != m_karts_properties.end(); ++i)
59
78
        delete *i;
60
79
    }
61
80
    m_karts_properties.clear();
62
 
    callback_manager->clear(CB_KART);
 
81
    m_selected_karts.clear();
 
82
    m_kart_available.clear();
 
83
    m_groups.clear();
 
84
    m_all_groups.clear();
 
85
    m_kart_search_path.clear();
63
86
}   // removeTextures
64
87
 
65
88
//-----------------------------------------------------------------------------
66
 
void KartPropertiesManager::loadKartData(bool dont_load_models)
67
 
{
68
 
    std::set<std::string> result;
69
 
    file_manager->listFiles(result, file_manager->getKartDir(), 
70
 
                            /*is_full_path*/ true);
71
 
 
72
 
    // Find out which characters are available and load them
73
 
    for(std::set<std::string>::iterator i = result.begin();
74
 
            i != result.end(); ++i)
75
 
    {
76
 
        std::string kart_file;
77
 
        try
78
 
        {
79
 
            kart_file = file_manager->getKartFile((*i)+".kart");
80
 
        }
81
 
        catch (std::exception& e)
82
 
        {
83
 
            (void)e;   // remove warning about unused variable
84
 
            continue;
85
 
        }
86
 
        FILE *f=fopen(kart_file.c_str(),"r");
87
 
        if(!f) continue;
88
 
        fclose(f);
89
 
        KartProperties* kp = new KartProperties();
90
 
        kp->load(kart_file, "tuxkart-kart", dont_load_models);
91
 
 
92
 
        // If the version of the kart file is not supported,
93
 
        // ignore this .kart file
94
 
        if(kp->getVersion()<stk_config->m_min_kart_version ||
95
 
            kp->getVersion()>stk_config->m_max_kart_version)
96
 
        {
97
 
            fprintf(stderr, "Warning: kart '%s' is not supported by this binary, ignored.\n",
98
 
                    kp->getIdent().c_str());
99
 
            delete kp;
100
 
            continue;
101
 
        }
102
 
 
103
 
        m_karts_properties.push_back(kp);
104
 
        m_kart_available.push_back(true);
105
 
        const std::vector<std::string>& groups=kp->getGroups();
106
 
        for(unsigned int g=0; g<groups.size(); g++)
107
 
        {
108
 
            if(m_groups.find(groups[g])==m_groups.end())
 
89
void KartPropertiesManager::reLoadAllKarts()
 
90
{
 
91
    for(KartPropertiesVector::iterator i  = m_karts_properties.begin();
 
92
        i != m_karts_properties.end(); ++i)
 
93
    {
 
94
        delete *i;
 
95
    }
 
96
    m_karts_properties.clear();
 
97
    m_selected_karts.clear();
 
98
    m_kart_available.clear();
 
99
    m_groups.clear();
 
100
    m_all_groups.clear();
 
101
    //m_kart_search_path.clear();
 
102
        loadAllKarts(false);
 
103
}  
 
104
//-----------------------------------------------------------------------------
 
105
/** Loads all kart properties and models.
 
106
 */
 
107
void KartPropertiesManager::loadAllKarts(bool loading_icon)
 
108
{
 
109
    m_all_kart_dirs.clear();
 
110
    for(std::vector<std::string>::const_iterator dir=m_kart_search_path.begin();
 
111
        dir!=m_kart_search_path.end(); dir++)
 
112
    {
 
113
        // First check if there is a kart in the current directory
 
114
        // -------------------------------------------------------
 
115
        if(loadKart(*dir)) continue;
 
116
 
 
117
        // If not, check each subdir of this directory.
 
118
        // --------------------------------------------
 
119
        std::set<std::string> result;
 
120
        file_manager->listFiles(result, *dir, /*is_full_path*/ true);
 
121
        for(std::set<std::string>::const_iterator subdir=result.begin();
 
122
            subdir!=result.end(); subdir++)
 
123
        {
 
124
            const bool loaded = loadKart(*dir+"/"+*subdir);
 
125
            
 
126
            if (loaded && loading_icon)
109
127
            {
110
 
                m_all_groups.push_back(groups[g]);
 
128
                GUIEngine::addLoadingIcon(irr_driver->getTexture(
 
129
                        *dir + "/"+*subdir + "/" +
 
130
                        m_karts_properties[m_karts_properties.size()-1]->getIconFile()
 
131
                                                                 )
 
132
                        );
111
133
            }
112
 
            m_groups[groups[g]].push_back(m_karts_properties.size()-1);
113
 
        }
 
134
        }   // for all files in the currently handled directory
114
135
    }   // for i
 
136
}   // loadAllKarts
 
137
 
 
138
//-----------------------------------------------------------------------------
 
139
/** Loads a single kart and (if not disabled) the oorresponding 3d model.
 
140
 *  \param filename Full path to the kart config file.
 
141
 */
 
142
bool KartPropertiesManager::loadKart(const std::string &dir)
 
143
{
 
144
    std::string config_filename=dir+"/kart.xml";
 
145
    FILE *f=fopen(config_filename.c_str(), "r");
 
146
    if(!f) return false;
 
147
    fclose(f);
 
148
 
 
149
    KartProperties* kart_properties;
 
150
    try
 
151
    {
 
152
        kart_properties = new KartProperties(config_filename);
 
153
    }
 
154
    catch (std::runtime_error& err)
 
155
    {
 
156
        std::cerr << "Giving up loading '" << config_filename.c_str()
 
157
                  << "' : " << err.what() << std::endl;
 
158
        return false;
 
159
    }
 
160
    
 
161
    // If the version of the kart file is not supported,
 
162
    // ignore this .kart file
 
163
    if (kart_properties->getVersion() < stk_config->m_min_kart_version ||
 
164
        kart_properties->getVersion() > stk_config->m_max_kart_version)
 
165
    {
 
166
        fprintf(stderr, "[KartPropertiesManager] Warning: kart '%s' is not supported by this binary, ignored.\n",
 
167
                kart_properties->getIdent().c_str());
 
168
        delete kart_properties;
 
169
        return false;
 
170
    }
 
171
 
 
172
    m_karts_properties.push_back(kart_properties);
 
173
    m_kart_available.push_back(true);
 
174
    const std::vector<std::string>& groups=kart_properties->getGroups();
 
175
    for(unsigned int g=0; g<groups.size(); g++)
 
176
    {
 
177
        if(m_groups.find(groups[g])==m_groups.end())
 
178
        {
 
179
            m_all_groups.push_back(groups[g]);
 
180
        }
 
181
        m_groups[groups[g]].push_back(m_karts_properties.size()-1);
 
182
    }
 
183
    m_all_kart_dirs.push_back(dir);
 
184
    return true;
115
185
}   // loadKartData
116
186
 
117
187
//-----------------------------------------------------------------------------
118
188
const int KartPropertiesManager::getKartId(const std::string &ident) const
119
 
{
 
189
{    
120
190
    for(KartPropertiesVector::const_iterator i  = m_karts_properties.begin();
121
191
        i != m_karts_properties.end(); ++i)
122
192
    {
 
193
        if(UserConfigParams::m_verbosity>=5)
 
194
            std::cout << "[KartPropertiesManager] getKartId : " << (*i)->getIdent().c_str() << std::endl;
123
195
        if ((*i)->getIdent() == ident)
124
196
            return i-m_karts_properties.begin();
125
197
    }
199
271
    for(KartPropertiesVector::const_iterator i  = m_karts_properties.begin();
200
272
        i != m_karts_properties.end(); ++i)
201
273
    {
202
 
                std::vector<std::string> groups=(*i)->getGroups();
 
274
        std::vector<std::string> groups=(*i)->getGroups();
203
275
        if (std::find(groups.begin(), groups.end(), group)==groups.end()) continue;
204
276
        if(count==n) return (int)(i-m_karts_properties.begin());
205
277
        count=count+1;
264
336
    // -----------------------------------------
265
337
    std::vector<bool> used;
266
338
    used.resize(getNumberOfKarts(), false);
267
 
 
 
339
    
268
340
    std::vector<std::string> all_karts;
269
341
    for(unsigned int i=0; i<existing_karts.size(); i++)
270
342
    {
271
 
        int id=getKartId(existing_karts[i].getKartName());
272
 
        used[id] = true;
 
343
        try
 
344
        {
 
345
            int id=getKartId(existing_karts[i].getKartName());
 
346
            used[id] = true;
 
347
        }
 
348
        catch (std::runtime_error& ex)
 
349
        {
 
350
            (void)ex;
 
351
            std::cerr << "[KartPropertiesManager] getRandomKartList : WARNING, can't find kart '" << existing_karts[i].getKartName() << "'\n";
 
352
        }
273
353
    }
274
354
 
275
355
    // Add karts from the current group
276
356
    // --------------------------------
277
 
    std::vector<int> karts = getKartsInGroup(user_config->m_kart_group);
 
357
    std::vector<int> karts = getKartsInGroup(UserConfigParams::m_kart_group);
278
358
    std::vector<int>::iterator k;
279
359
    // Remove karts that are already used or generally not available
280
360
    // (i.e. locked or not available on all clients)
286
366
        else
287
367
            i++;
288
368
    }
289
 
    std::srand((unsigned int)std::time(0));
290
369
    std::random_shuffle(karts.begin(), karts.end());
291
370
 
292
371
    // Loop over all karts to fill till either all slots are filled, or
293
372
    // there are no more karts in the current group
294
373
    while(count>0 && karts.size()>0)
295
374
    {
296
 
        used[karts.back()] = true;
 
375
        //used[karts.back()] = true;
297
376
        random_karts.push_back(m_karts_properties[karts.back()]->getIdent());
298
377
        karts.pop_back();
299
378
        count --;
311
390
            karts.push_back(i);
312
391
    }
313
392
    std::random_shuffle(karts.begin(), karts.end());
 
393
    
314
394
    // Then fill up the remaining empty spaces
315
 
    while(count>0 && karts.size()>0)
 
395
    do
316
396
    {
317
 
        random_karts.push_back(m_karts_properties[karts.back()]->getIdent());
318
 
        karts.pop_back();
319
 
        count --;
320
 
    }
 
397
        while(count>0 && karts.size()>0)
 
398
        {
 
399
            random_karts.push_back(m_karts_properties[karts.back()]->getIdent());
 
400
            karts.pop_back();
 
401
            count --;
 
402
        }
 
403
        
 
404
        // we used all karts but still need more... we'll have no choice but
 
405
        // to use the same karts more than once.
 
406
        if (count>0 && karts.size() == 0)
 
407
        {
 
408
            for(unsigned int i=0; i<getNumberOfKarts(); i++)
 
409
            {
 
410
                if(!used[i] && m_kart_available[i] &&
 
411
                   !unlock_manager->isLocked(m_karts_properties[i]->getIdent()) )
 
412
                    karts.push_back(i);
 
413
            }
 
414
            // If there are no unused karts, use used karts again.
 
415
            // This means that e.g. if only one kart is availabe, which is
 
416
            // used by the player, it will still be used by AI karts (which
 
417
            // can be useful for debugging).
 
418
            if(karts.size()==0)
 
419
            {
 
420
                for(unsigned int i=0; i<getNumberOfKarts(); i++)
 
421
                {
 
422
                    if(m_kart_available[i] &&
 
423
                        !unlock_manager->isLocked(m_karts_properties[i]->getIdent()) )
 
424
                        karts.push_back(i);
 
425
                }
 
426
            }
 
427
            std::random_shuffle(karts.begin(), karts.end());
 
428
        }
 
429
        
 
430
    } while(count>0);
 
431
    
321
432
    // There should always be enough karts
322
433
    assert(count==0);
323
434
    return random_karts;