/* ================ idCollisionModelManagerLocal::LoadCollisionModelFile ================ */ bool idCollisionModelManagerLocal::LoadCollisionModelFile( const char* name, unsigned int mapFileCRC ) { idToken token; idLexer* src; unsigned int crc; // load it idStrStatic< MAX_OSPATH > fileName = name; // check for generated file idStrStatic< MAX_OSPATH > generatedFileName = fileName; generatedFileName.Insert( "generated/", 0 ); generatedFileName.SetFileExtension( CM_BINARYFILE_EXT ); // if we are reloading the same map, check the timestamp // and try to skip all the work ID_TIME_T currentTimeStamp = fileSystem->GetTimestamp( fileName ); // see if we have a generated version of this bool loaded = false; idFileLocal file( fileSystem->OpenFileReadMemory( generatedFileName ) ); if( file != NULL ) { int numEntries = 0; file->ReadBig( numEntries ); file->ReadString( mapName ); file->ReadBig( crc ); idStrStatic< 32 > fileID; idStrStatic< 32 > fileVersion; file->ReadString( fileID ); file->ReadString( fileVersion ); if( fileID == CM_FILEID && fileVersion == CM_FILEVERSION && crc == mapFileCRC && numEntries > 0 ) { loaded = true; // DG: moved this up here to prevent segfaults, see below for( int i = 0; i < numEntries; i++ ) { cm_model_t* model = LoadBinaryModelFromFile( file, currentTimeStamp ); // DG: handle the case that loading the binary model fails gracefully // (otherwise we'll get a segfault when someone wants to use models[numModels]) if( model == NULL ) { loaded = false; break; } // DG end models[ numModels ] = model; numModels++; } } } if( !loaded ) { fileName.SetFileExtension( CM_FILE_EXT ); src = new( TAG_COLLISION ) idLexer( fileName ); src->SetFlags( LEXFL_NOSTRINGCONCAT | LEXFL_NODOLLARPRECOMPILE ); if( !src->IsLoaded() ) { delete src; return false; } int numEntries = 0; idFileLocal outputFile( fileSystem->OpenFileWrite( generatedFileName, "fs_basepath" ) ); if( outputFile != NULL ) { outputFile->WriteBig( numEntries ); outputFile->WriteString( mapName ); outputFile->WriteBig( mapFileCRC ); outputFile->WriteString( CM_FILEID ); outputFile->WriteString( CM_FILEVERSION ); } if( !src->ExpectTokenString( CM_FILEID ) ) { common->Warning( "%s is not an CM file.", fileName.c_str() ); delete src; return false; } if( !src->ReadToken( &token ) || token != CM_FILEVERSION ) { common->Warning( "%s has version %s instead of %s", fileName.c_str(), token.c_str(), CM_FILEVERSION ); delete src; return false; } if( !src->ExpectTokenType( TT_NUMBER, TT_INTEGER, &token ) ) { common->Warning( "%s has no map file CRC", fileName.c_str() ); delete src; return false; } crc = token.GetUnsignedLongValue(); if( mapFileCRC && crc != mapFileCRC ) { common->Printf( "%s is out of date\n", fileName.c_str() ); delete src; return false; } // parse the file while( 1 ) { if( !src->ReadToken( &token ) ) { break; } if( token == "collisionModel" ) { cm_model_t* model = ParseCollisionModel( src ); if( model == NULL ) { delete src; return false; } if( outputFile != NULL ) { WriteBinaryModelToFile( model, outputFile, currentTimeStamp ); numEntries++; } continue; } src->Error( "idCollisionModelManagerLocal::LoadCollisionModelFile: bad token \"%s\"", token.c_str() ); } delete src; if( outputFile != NULL ) { outputFile->Seek( 0, FS_SEEK_SET ); outputFile->WriteBig( numEntries ); } } return true; }
/* ================ idCollisionModelManagerLocal::LoadCollisionModelFile ================ */ bool idCollisionModelManagerLocal::LoadCollisionModelFile( const char *name, unsigned int mapFileCRC ) { idStr fileName; idToken token; idLexer *src; unsigned int crc; // load it fileName = name; fileName.SetFileExtension( CM_FILE_EXT ); src = new idLexer( fileName ); src->SetFlags( LEXFL_NOSTRINGCONCAT | LEXFL_NODOLLARPRECOMPILE ); if ( !src->IsLoaded() ) { delete src; return false; } if ( !src->ExpectTokenString( CM_FILEID ) ) { common->Warning( "%s is not an CM file.", fileName.c_str() ); delete src; return false; } if ( !src->ReadToken( &token ) || token != CM_FILEVERSION ) { common->Warning( "%s has version %s instead of %s", fileName.c_str(), token.c_str(), CM_FILEVERSION ); delete src; return false; } if ( !src->ExpectTokenType( TT_NUMBER, TT_INTEGER, &token ) ) { common->Warning( "%s has no map file CRC", fileName.c_str() ); delete src; return false; } crc = token.GetUnsignedLongValue(); if ( mapFileCRC && crc != mapFileCRC ) { common->Printf( "%s is out of date\n", fileName.c_str() ); delete src; return false; } // parse the file while ( 1 ) { if ( !src->ReadToken( &token ) ) { break; } if ( token == "collisionModel" ) { if ( !ParseCollisionModel( src ) ) { delete src; return false; } continue; } src->Error( "idCollisionModelManagerLocal::LoadCollisionModelFile: bad token \"%s\"", token.c_str() ); } delete src; return true; }