Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

itemrepository.cpp

Go to the documentation of this file.
00001 
00002 /***************************************************************************
00003                           itemrepository.cpp   -  description
00004                              -------------------
00005     begin                : Thu Jul 28 2001
00006     copyright            : (C) 2001 by Martin Bickel
00007     email                : bickel@asc-hq.org
00008  ***************************************************************************/
00013 /***************************************************************************
00014  *                                                                         *
00015  *   This program is free software; you can redistribute it and/or modify  *
00016  *   it under the terms of the GNU General Public License as published by  *
00017  *   the Free Software Foundation; either version 2 of the License, or     *
00018  *   (at your option) any later version.                                   *
00019  *                                                                         *
00020  ***************************************************************************/
00021 
00022 #include <map>
00023 #include <vector>
00024 #include "typen.h"
00025 #include "itemrepository.h"
00026 #include "textfileparser.h"
00027 #include "sgstream.h"
00028 #include "textfile_evaluation.h"
00029 #include "messaginghub.h"
00030 
00031 
00032 SigC::Signal0<void> dataLoaderTicker;
00033 
00034 
00035 const char* cacheFileName = "asc2.cache";
00036 
00037 typedef vector<TextFileDataLoader*> DataLoaders;
00038 DataLoaders dataLoaders;
00039 DataLoaders dataLoadersToDelete;
00040 
00041 
00042 typedef map<ASCString,TextPropertyList> TextFileRepository;
00043 TextFileRepository textFileRepository;
00044 
00045 
00046 void duplicateIDError ( const ASCString& itemtype, int id, const ASCString& file1, const ASCString& name1, const ASCString&  file2, const ASCString& name2 )
00047 {
00048    fatalError ( "Conflicting IDs !\n"
00049                 "These two " + itemtype + "s use both the ID of " + strrr ( id ) + "\n" +
00050                 " " + name1 + " from file " + file1 + "\n" +
00051                 " " + name2 + " from file " + file2 + "\n\n" +
00052                 "This is NOT a bug of ASC, it is conflict between two data files.");
00053 }
00054 
00055 
00056 template<class T> 
00057 void ItemRepository<T>::RegisterID::operator() (int id )
00058 {
00059    typename ObjectMap::iterator i = repository.hash.find ( id );
00060    if ( i != repository.hash.end() && i->second )
00061       duplicateIDError ( repository.typeName, id, object->location, object->name, i->second->location, i->second->name );
00062    repository.hash[ id ] = object;
00063 }
00064 
00065 
00066 
00067 template<class T>
00068 void ItemRepository<T>::add( T* obj )
00069 {
00070    RegisterID reg(*this, obj);
00071    reg( obj->id );
00072 
00073    for_each ( obj->secondaryIDs.begin(), obj->secondaryIDs.end(), reg );
00074 
00075 
00076    container.push_back( obj );
00077 }
00078 
00079 
00080 template<class T>
00081 void ItemRepositoryLoader<T>::readTextFiles( PropertyReadingContainer& prc, const ASCString& fileName, const ASCString& location )
00082 {
00083    T* t = new T;
00084    t->runTextIO ( prc );
00085 
00086    t->filename = fileName;
00087    t->location = location;
00088    add ( t );
00089 }
00090 
00091 
00092 template<class T>
00093 void ItemRepositoryLoader<T>::read( tnstream& stream )
00094 {
00095    int version = stream.readInt();
00096    if ( version != 1 )
00097       throw tinvalidversion( stream.getLocation(), 1, version );
00098    int num = stream.readInt();
00099    for ( int i = 0; i< num; ++i ) {
00100       dataLoaderTicker();
00101 
00102       T* t = new T;
00103       t->read( stream );
00104 
00105       t->filename = stream.readString();
00106       t->location = stream.readString();
00107       dataLoaderTicker();
00108 
00109       add ( t );
00110       // add ( T::newFromStream(stream ));
00111    }
00112 }
00113 
00114 
00115 template<class T>
00116 void ItemRepositoryLoader<T>::write( tnstream& stream )
00117 {
00118    stream.writeInt( 1 );
00119    stream.writeInt( ItemRepository<T>::container.size() );
00120    for ( typename ItemRepository<T>::ItemContainerType::iterator i = ItemRepository<T>::container.begin(); i != ItemRepository<T>::container.end(); ++i ) {
00121        (*i)->write( stream );
00122        stream.writeString ( (*i)->filename );
00123        stream.writeString ( (*i)->location );
00124    }
00125 }
00126 
00127 
00128 template<class T>
00129 void ItemRepository<T>::addIdTranslation( int from, int to )
00130 {
00131     idTranslation[from] = to;
00132 }
00133 
00134 MineTypeRepository  mineTypeRepository;
00135 
00136 
00137 MineTypeRepository::MineTypeRepository() : ItemRepository<MineType>("Mines")
00138 {
00139    add( new MineType( cmantipersonnelmine ) );
00140    add( new MineType( cmantitankmine ) );
00141    add( new MineType( cmmooredmine ) );
00142    add( new MineType( cmfloatmine ) );
00143 }
00144 
00145 
00146 ItemRepositoryLoader<Vehicletype>  vehicleTypeRepository( "vehicletype" );
00147 ItemRepositoryLoader<TerrainType>  terrainTypeRepository( "terraintype" );
00148 ItemRepositoryLoader<ObjectType>   objectTypeRepository ( "objecttype" );
00149 ItemRepositoryLoader<BuildingType> buildingTypeRepository ("buildingtype");
00150 ItemRepositoryLoader<Technology>   technologyRepository ( "technology");
00151 
00152 TechAdapterContainer techAdapterContainer;
00153 
00154 namespace {
00155    class Foo {
00156    public:
00157       Foo() { objectTypeRepository.addIdTranslation( 12998, 1 ); };
00158    } foo;
00159 };
00160 
00161 class TechAdapterLoader : public TextFileDataLoader {
00162       void readTextFiles(PropertyReadingContainer& prc, const ASCString& fileName, const ASCString& location ) {
00163            TechAdapter* ta = new TechAdapter;
00164            ta->runTextIO ( prc );
00165 
00166            ta->filename = fileName;
00167            ta->location = location;
00168            techAdapterContainer.push_back ( ta );
00169       };
00170 
00171       void read ( tnstream& stream ){
00172          readPointerContainer( techAdapterContainer, stream );
00173       };
00174 
00175       void write ( tnstream& stream ){
00176          writePointerContainer( techAdapterContainer, stream );
00177       };
00178       ASCString getTypeName() {
00179          return "techadapter";
00180       };
00181 };
00182 
00183 
00184 void  loadalltextfiles ( );
00185 
00186 const int cacheVersion = 27;
00187 
00188 class FileCache {
00189       vector<tfindfile::FileInfo> actualFileInfo;
00190       tnstream* stream;
00191       bool current;
00192       bool checkForModification ();
00193    public:
00194       FileCache( );
00195       bool isCurrent() { return current; };
00196       void load();
00197       void write();
00198 
00199       ~FileCache();
00200 };
00201 
00202 FileCache::FileCache( )
00203           :stream(NULL)
00204 {
00205    tfindfile::FileInfo fi;
00206    {
00207       tfindfile f ( "*.ascdat", tfindfile::AllDirs, tfindfile::OutsideContainer);
00208       while ( f.getnextname( fi ))
00209          actualFileInfo.push_back ( fi );
00210    }
00211    {
00212       tfindfile f ( "*.asctxt", tfindfile::AllDirs, tfindfile::OutsideContainer);
00213       while ( f.getnextname( fi ))
00214          actualFileInfo.push_back ( fi );
00215    }
00216 
00217    if ( exist ( cacheFileName )) {
00218       stream = new tnfilestream ( cacheFileName, tnstream::reading );
00219       int version = stream->readInt();
00220 
00221       if ( version == cacheVersion )
00222          current = checkForModification();
00223       else
00224          current = false;
00225    } else
00226       current = false;
00227 }
00228 
00229 bool FileCache::checkForModification (  )
00230 {
00231    vector<tfindfile::FileInfo> cacheFileInfo;
00232    readClassContainer ( cacheFileInfo, *stream );
00233 
00234    if ( cacheFileInfo.size() != actualFileInfo.size() )
00235       return false;
00236 
00237    for ( vector<tfindfile::FileInfo>::iterator i = actualFileInfo.begin(); i != actualFileInfo.end(); ++i ) {
00238       bool found = false;
00239       for ( vector<tfindfile::FileInfo>::iterator j = cacheFileInfo.begin(); j != cacheFileInfo.end(); ++j )
00240          if ( i->name == j->name ) {
00241             found = true;
00242             if ( i->size != j->size )
00243                return false;
00244 
00245             if ( i->date != j->date )
00246                return false;
00247 
00248             break;
00249          }
00250 
00251       if ( !found)
00252          return false;
00253    }
00254 
00255 
00256    return true;
00257 }
00258 
00259 
00260 void FileCache::load()
00261 {
00262    for ( DataLoaders::iterator i = dataLoaders.begin(); i != dataLoaders.end(); ++i) {
00263       displayLogMessage ( 5, "loading all of " + (*i)->getTypeName() + " from cache ... ");
00264       (*i)->read ( *stream );
00265       displayLogMessage ( 5, "completed \n ");
00266    }
00267 }
00268 
00269 
00270 void FileCache::write()
00271 {
00272    if ( stream )
00273       delete stream;
00274 
00275    stream = new tn_file_buf_stream ( cacheFileName, tnstream::writing );
00276 
00277    stream->writeInt ( cacheVersion );
00278    writeClassContainer ( actualFileInfo, *stream );
00279 
00280    for ( DataLoaders::iterator i = dataLoaders.begin(); i != dataLoaders.end(); ++i)
00281       (*i)->write ( *stream );
00282 
00283 }
00284 
00285 
00286 
00287 FileCache::~FileCache()
00288 {
00289    if ( stream ) {
00290       delete stream;
00291       stream = NULL;
00292    }
00293    for ( DataLoaders::iterator i = dataLoadersToDelete.begin(); i != dataLoadersToDelete.end(); ++i)
00294       delete *i;
00295 }
00296 
00297 
00298 
00299 void registerDataLoader( TextFileDataLoader* dataLoader )
00300 {
00301    dataLoaders.push_back ( dataLoader );
00302    dataLoadersToDelete.push_back ( dataLoader );
00303 }
00304 
00305 void registerDataLoader( TextFileDataLoader& dataLoader )
00306 {
00307    dataLoaders.push_back ( &dataLoader );
00308 }
00309 
00310 
00311 void  loadAllData( bool useCache )
00312 {
00313    FileCache cache;
00314 
00315    registerDataLoader( vehicleTypeRepository );
00316    registerDataLoader( terrainTypeRepository );
00317    registerDataLoader( objectTypeRepository );
00318    registerDataLoader( buildingTypeRepository );
00319    registerDataLoader( technologyRepository );
00320    registerDataLoader( new TechAdapterLoader() );
00321    registerDataLoader( new ItemFiltrationSystem::DataLoader() );
00322 
00323 
00324    if ( cache.isCurrent() && useCache ) {
00325       try {
00326          cache.load();
00327       }
00328       catch ( tinvalidversion err ) {
00329          fatalError("the cache seems to have been generated with a newer version of ASC than this one.\nPlease upgrade to that version, or delete " + ASCString(cacheFileName) + " and try again");
00330       }
00331       displayLogMessage ( 4, "loading of cache completed\n");
00332    } else {
00333       MessagingHub::Instance().statusInformation("rebuilding data cache, please be patient");
00334       
00335       loadalltextfiles();
00336 
00337       for ( DataLoaders::iterator dl = dataLoaders.begin(); dl != dataLoaders.end(); ++dl) {
00338          TextPropertyList& tpl = textFileRepository[ (*dl)->getTypeName() ];
00339          for ( TextPropertyList::iterator i = tpl.begin(); i != tpl.end(); i++ ) {
00340             dataLoaderTicker();
00341 
00342             if ( !(*i)->isAbstract() ) {
00343                PropertyReadingContainer pc ( (*dl)->getTypeName(), *i );
00344 
00345                displayLogMessage ( 5, "loading " + (*i)->location );
00346                (*dl)->readTextFiles( pc, (*i)->fileName, (*i)->location );
00347                displayLogMessage ( 5, " done\n");
00348             }
00349          }
00350 
00351          displayLogMessage ( 4, "loading all of " + (*dl)->getTypeName() + "  completed\n");
00352 
00353       }
00354 
00355       if ( useCache ) {
00356          try {
00357             cache.write();
00358          }
00359          catch ( tfileerror err ) {
00360             fatalError("error writing cache file");
00361          }
00362       }
00363 
00364       textFileRepository.clear();
00365    }
00366 
00367 }
00368 
00369 
00370 
00371 
00372 
00373 void  loadalltextfiles ( )
00374 {
00375    tfindfile ff ( "*.asctxt" );
00376    ASCString c = ff.getnextname();
00377 
00378    while( !c.empty() ) {
00379       dataLoaderTicker();
00380 
00381       tnfilestream s ( c, tnstream::reading );
00382 
00383       displayLogMessage ( 6, "loadalltextfiles :: loading " + s.getLocation() + ", " );
00384 
00385       TextFormatParser tfp ( &s );
00386 
00387       displayLogMessage ( 5, "TFP running... " );
00388 
00389       TextPropertyGroup* tpg = tfp.run();
00390 
00391       textFileRepository[tpg->typeName].push_back ( tpg );
00392 
00393       displayLogMessage ( 5, "done\n" );
00394 
00395       c = ff.getnextname();
00396    }
00397    displayLogMessage ( 4, "loadalltextfiles completed\n");
00398 
00399    displayLogMessage ( 4, "Building inheritance...");
00400 
00401    displayLogMessage ( 10, " Printing all .ASCTXT files after inheritance and aliases have been resolved\n");
00402    for ( TextFileRepository::iterator i = textFileRepository.begin(); i != textFileRepository.end(); i++ ) {
00403       i->second.buildIDs();
00404       for ( TextPropertyList::iterator j = i->second.begin(); j != i->second.end(); j++ ) {
00405           displayLogMessage( 9, "Building inheritance: " + (*j)->location + "\n");
00406           (*j)->buildInheritance( i->second );
00407           if ( MessagingHub::Instance().getVerbosity() >= 10 )
00408              (*j)->print();
00409       }
00410    }
00411    displayLogMessage ( 4, "done\n");
00412 }
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420 deallocating_vector<ItemFiltrationSystem::ItemFilter*> ItemFiltrationSystem::itemFilters;
00421 
00422 
00423 ItemFiltrationSystem::ItemFilter::ItemFilter( const ASCString& _name, const IntRangeArray& unitsetIDs, bool _active )
00424 {
00425    name = "UnitSet: " + _name;
00426    units = unitsetIDs;
00427    active = _active;
00428 }
00429 
00430 
00431 void ItemFiltrationSystem::ItemFilter::runTextIO ( PropertyContainer& pc )
00432 {
00433     if ( pc.find ( "Buildings"))
00434       pc.addIntRangeArray ( "Buildings", buildings );
00435     if ( pc.find ( "Vehicles"))
00436       pc.addIntRangeArray ( "Vehicles", units );
00437     if ( pc.find ( "Objects"))
00438        pc.addIntRangeArray ( "Objects", objects );
00439     if ( pc.find ( "Terrain"))
00440       pc.addIntRangeArray ( "Terrain", terrain );
00441     if ( pc.find ( "Technologies"))
00442       pc.addIntRangeArray ( "Technologies", technologies );
00443     pc.addBool ( "activated", active, false );
00444     pc.addString ( "name", name );
00445 }
00446 
00447 void ItemFiltrationSystem::ItemFilter::read ( tnstream& stream )
00448 {
00449    int version = stream.readInt();
00450    if ( version > 2 )
00451       throw tinvalidversion( stream.getDeviceName(), 2, version );
00452    readClassContainer ( buildings, stream );
00453    readClassContainer ( objects, stream );
00454    readClassContainer ( units, stream );
00455    readClassContainer ( terrain, stream );
00456    if ( version >= 2 )
00457       readClassContainer ( technologies, stream );
00458 
00459    active = stream.readInt();
00460    name = stream.readString();
00461 }
00462 
00463 void ItemFiltrationSystem::ItemFilter::write ( tnstream& stream )
00464 {
00465    stream.writeInt ( 2 );
00466    writeClassContainer ( buildings, stream );
00467    writeClassContainer ( objects, stream );
00468    writeClassContainer ( units, stream );
00469    writeClassContainer ( terrain, stream );
00470    writeClassContainer ( technologies, stream );
00471    stream.writeInt ( active );
00472    stream.writeString ( name );
00473 }
00474 
00475 
00476 
00477 bool ItemFiltrationSystem::ItemFilter::isContained ( IntRangeArray& arr, int id )
00478 {
00479    for ( IntRangeArray::iterator i = arr.begin(); i != arr.end(); i++ )
00480       if ( id >= i->from && id <= i->to )
00481          return true;
00482    return false;
00483 }
00484 
00485 
00486 
00487 bool ItemFiltrationSystem::ItemFilter::isContained ( ItemFiltrationSystem::Category cat, int id )
00488 {
00489    switch ( cat ) {
00490       case Building: return isContained ( buildings, id );
00491       case Vehicle: return isContained ( units, id );
00492       case Object: return isContained ( objects, id );
00493       case Terrain: return isContained ( terrain, id );
00494       case Technology: return isContained ( technologies, id );
00495    };
00496    return false;
00497 }
00498 
00499 bool ItemFiltrationSystem::isFiltered ( ItemFiltrationSystem::Category cat, int id )
00500 {
00501    for ( vector<ItemFilter*>::iterator i = itemFilters.begin(); i != itemFilters.end(); i++ )
00502       if ( (*i)->isContained ( cat, id ) )
00503          if ( (*i)->isActive() )
00504             return true;
00505 
00506    return false;
00507 }
00508 
00509 
00510 bool ItemFiltrationSystem::isFiltered( const Vehicletype* item )
00511 {
00512    return isFiltered( Vehicle, item->id );
00513 }
00514 
00515 bool ItemFiltrationSystem::isFiltered( const BuildingType* item )
00516 {
00517    return isFiltered( Building, item->id );
00518 }
00519 
00520 bool ItemFiltrationSystem::isFiltered( const ObjectType* item )
00521 {
00522    return isFiltered( Object, item->id );
00523 }
00524 
00525 bool ItemFiltrationSystem::isFiltered( const TerrainType* item )
00526 {
00527    return isFiltered( Terrain, item->id );
00528 }
00529 
00530 bool ItemFiltrationSystem::isFiltered( const MineType* item )
00531 {
00532    return false;
00533 }
00534 
00535 
00536 void ItemFiltrationSystem::DataLoader::readTextFiles( PropertyReadingContainer& prc, const ASCString& fileName, const ASCString& location )
00537 {
00538    ItemFilter* itf = new ItemFilter;
00539    itf->runTextIO ( prc );
00540 
00541    // bmtt->filename = (*i)->fileName;
00542    // bmtt->location = (*i)->location;
00543    ItemFiltrationSystem::itemFilters.push_back ( itf );
00544 }
00545 
00546 void ItemFiltrationSystem::DataLoader::read ( tnstream& stream )
00547 {
00548    stream.readInt();
00549    readPointerContainer( ItemFiltrationSystem::itemFilters, stream );
00550 }
00551 
00552 void ItemFiltrationSystem::DataLoader::write ( tnstream& stream )
00553 {
00554    stream.writeInt ( 1 );
00555    writePointerContainer( ItemFiltrationSystem::itemFilters, stream );
00556 }
00557 

Generated on Tue Jun 24 01:27:44 2008 for Advanced Strategic Command by  doxygen 1.4.2