CGraphMerger::CGraphMerger( LPCSTR game_graph_id, LPCSTR name, bool rebuild ) { // load all the graphs Phase("Processing level graphs"); CInifile *Ini = new CInifile(INI_FILE); if (!Ini->section_exist("levels")) THROW(false); R_ASSERT (Ini->section_exist("levels")); tGraphHeader.m_guid = generate_guid(); GRAPH_P_MAP tpGraphs; string4096 S1, S2; CGameGraph::SLevel tLevel; u32 dwOffset = 0; u32 l_dwPointOffset = 0; LEVEL_POINT_STORAGE l_tpLevelPoints; l_tpLevelPoints.clear (); xr_set<CLevelInfo> levels; xr_vector<LPCSTR> needed_levels; string4096 levels_string; strcpy_s (levels_string,name); strlwr (levels_string); fill_needed_levels (levels_string,needed_levels); read_levels ( Ini, levels, rebuild, &needed_levels ); xr_set<CLevelInfo>::const_iterator I = levels.begin(); xr_set<CLevelInfo>::const_iterator E = levels.end(); for ( ; I != E; ++I) { tLevel.m_offset = (*I).m_offset; tLevel.m_name = (*I).m_name; strcpy_s (S1,sizeof(S1),*(*I).m_name); strconcat (sizeof(S2),S2,name,S1); strconcat (sizeof(S1),S1,S2,"\\"); tLevel.m_id = (*I).m_id; tLevel.m_section = (*I).m_section; Msg ("%9s %2d %s","level",tLevel.id(),*tLevel.m_name); string_path _0, _1; generate_temp_file_name ("local_graph_",*tLevel.m_name,_0); generate_temp_file_name ("raw_cross_table_",*tLevel.m_name,_1); string_path level_folder; FS.update_path (level_folder,"$game_levels$",*tLevel.m_name); strcat (level_folder,"\\"); CGameGraphBuilder().build_graph (_0,_1,level_folder); ::CLevelGameGraph *tpLevelGraph = new ::CLevelGameGraph( _0, _1, &tLevel, level_folder, dwOffset, tLevel.id(), Ini ); dwOffset += tpLevelGraph->m_tpGraph->header().vertex_count(); R_ASSERT2 (tpGraphs.find(tLevel.id()) == tpGraphs.end(),"Level ids _MUST_ be different!"); tpGraphs.insert (mk_pair(tLevel.id(),tpLevelGraph)); tGraphHeader.m_levels.insert(std::make_pair(tLevel.id(),tLevel)); } R_ASSERT(tpGraphs.size()); Phase("Adding interconnection points"); { GRAPH_P_PAIR_IT I = tpGraphs.begin(); GRAPH_P_PAIR_IT E = tpGraphs.end(); for ( ; I != E; I++) { VERTEX_PAIR_IT i = (*I).second->m_tVertexMap.begin(); VERTEX_PAIR_IT e = (*I).second->m_tVertexMap.end(); for ( ; i != e; i++) if ((*i).second.caConnectName[0]) { GRAPH_P_PAIR_IT K; VERTEX_PAIR_IT M; CGameGraph::CEdge tGraphEdge; SConnectionVertex &tConnectionVertex = (*i).second; K = tpGraphs.find(tConnectionVertex.dwLevelID); if (K == tpGraphs.end()) { Msg ("Cannot find level with level_id %d. Connection point will not be generated!",tConnectionVertex.dwLevelID); continue; } R_ASSERT (K != tpGraphs.end()); M = (*K).second->m_tVertexMap.find(tConnectionVertex.caConnectName); if (M == (*K).second->m_tVertexMap.end()) { Msg ("Level %s with id %d has an INVALID connection point %s,\nwhich references to graph point %s on the level %s with id %d\n",*(*I).second->m_tLevel.name(),(*I).second->m_tLevel.id(),(*i).first,tConnectionVertex.caConnectName,*(*K).second->m_tLevel.name(),(*K).second->m_tLevel.id()); R_ASSERT (M != (*K).second->m_tVertexMap.end()); } // if (!stricmp("l06_rostok",*(*I).second->m_tLevel.name())) { // __asm int 3; // } Msg ("Level %s with id %d has VALID connection point %s,\nwhich references to graph point %s on the level %s with id %d\n",*(*I).second->m_tLevel.name(),(*I).second->m_tLevel.id(),(*i).first,tConnectionVertex.caConnectName,*(*K).second->m_tLevel.name(),(*K).second->m_tLevel.id()); VERIFY (((*M).second.tGraphID + (*K).second->m_dwOffset) < (u32(1) << (8*sizeof(GameGraph::_GRAPH_ID)))); tGraphEdge.m_vertex_id = (GameGraph::_GRAPH_ID)((*M).second.tGraphID + (*K).second->m_dwOffset); VERIFY3 (tConnectionVertex.tGraphID < (*I).second->m_tpVertices.size(),"Rebuild graph for the level",*(*I).second->m_tLevel.name()); VERIFY3 ((*M).second.tGraphID < (*K).second->m_tpVertices.size(),"Rebuild graph for the level",*(*K).second->m_tLevel.name()); tGraphEdge.m_path_distance = (*I).second->m_tpVertices[tConnectionVertex.tGraphID].tGlobalPoint.distance_to((*K).second->m_tpVertices[(*M).second.tGraphID].tGlobalPoint); (*I).second->vfAddEdge ((*i).second.tGraphID,tGraphEdge); // tGraphEdge.dwVertexNumber = (*i).second.tGraphID + (*I).second->m_dwOffset; // (*K).second->vfAddEdge ((*M).second.tGraphID,tGraphEdge); } } } // counting edges { tGraphHeader.m_edge_count = 0; tGraphHeader.m_death_point_count = 0; GRAPH_P_PAIR_IT I = tpGraphs.begin(); GRAPH_P_PAIR_IT E = tpGraphs.end(); for ( ; I != E; I++) { VERIFY ((u32(tGraphHeader.m_edge_count) + (*I).second->dwfGetEdgeCount()) < (u32(1) << (8*sizeof(GameGraph::_GRAPH_ID)))); tGraphHeader.m_edge_count += (GameGraph::_GRAPH_ID)(*I).second->dwfGetEdgeCount(); tGraphHeader.m_death_point_count+= (*I).second->dwfGetDeathPointCount(); } } /////////////////////////////////////////////////// // save all the graphs Phase("Saving graph being merged"); CMemoryWriter F; tGraphHeader.m_version = XRAI_CURRENT_VERSION; VERIFY (dwOffset < (u32(1) << (8*sizeof(GameGraph::_GRAPH_ID)))); tGraphHeader.m_vertex_count = (GameGraph::_GRAPH_ID)dwOffset; tGraphHeader.save (&F); u32 vertex_count = 0; dwOffset *= sizeof(CGameGraph::CVertex); u32 l_dwOffset = F.size(); l_dwPointOffset = dwOffset + tGraphHeader.edge_count()*sizeof(CGameGraph::CEdge); u32 l_dwStartPointOffset = l_dwPointOffset; { GRAPH_P_PAIR_IT I = tpGraphs.begin(); GRAPH_P_PAIR_IT E = tpGraphs.end(); for ( ; I != E; I++) { (*I).second->vfSaveVertices (F,dwOffset,l_dwPointOffset,&l_tpLevelPoints); vertex_count += (*I).second->m_tpGraph->header().vertex_count(); } } { GRAPH_P_PAIR_IT I = tpGraphs.begin(); GRAPH_P_PAIR_IT E = tpGraphs.end(); for ( ; I != E; I++) (*I).second->vfSaveEdges(F); } { l_tpLevelPoints.clear (); GRAPH_P_PAIR_IT I = tpGraphs.begin(); GRAPH_P_PAIR_IT E = tpGraphs.end(); for ( ; I != E; I++) l_tpLevelPoints.insert(l_tpLevelPoints.end(),(*I).second->m_tpLevelPoints.begin(),(*I).second->m_tpLevelPoints.end()); } R_ASSERT2 (l_dwStartPointOffset == F.size() - l_dwOffset,"Graph file format is corrupted"); { LEVEL_POINT_STORAGE::const_iterator I = l_tpLevelPoints.begin(); LEVEL_POINT_STORAGE::const_iterator E = l_tpLevelPoints.end(); for ( ; I != E; ++I) save_data (*I,F); } { GRAPH_P_PAIR_IT I = tpGraphs.begin(); GRAPH_P_PAIR_IT E = tpGraphs.end(); for ( ; I != E; I++) { Msg ("cross_table offset: %d",F.size()); (*I).second->save_cross_table (F); } } string256 l_caFileName; strcpy_s (l_caFileName,game_graph_id); F.save_to (l_caFileName); // free all the graphs Phase("Freeing resources being allocated"); { GRAPH_P_PAIR_IT I = tpGraphs.begin(); GRAPH_P_PAIR_IT E = tpGraphs.end(); for ( ; I != E; I++) xr_free((*I).second); } xr_delete (Ini); }
void CGameGraphBuilder::save_graph (const float &start, const float &amount) { Progress (start); Msg ("Saving graph"); // header CMemoryWriter writer; CGameGraph::CHeader header; header.m_version = XRAI_CURRENT_VERSION; VERIFY (graph().vertices().size() < (u32(1) << (8*sizeof(GameGraph::_GRAPH_ID)))); header.m_vertex_count = (GameGraph::_GRAPH_ID)graph().vertices().size(); VERIFY (graph().edge_count() < (u32(1) << (8*sizeof(GameGraph::_GRAPH_ID)))); header.m_edge_count = (GameGraph::_GRAPH_ID)graph().edge_count(); header.m_death_point_count = 0; header.m_guid = m_graph_guid; // levels CGameGraph::SLevel level; level.m_offset.set (0,0,0); level.m_id = 0; level.m_name = m_level_name; level.m_section = ""; level.m_guid = level_graph().header().guid(); header.m_levels.insert (std::make_pair(level.m_id,level)); header.save (&writer); { u32 edge_offset = graph().vertices().size()*sizeof(CGameGraph::CVertex); graph_type::const_vertex_iterator I = graph().vertices().begin(); graph_type::const_vertex_iterator E = graph().vertices().end(); for ( ; I != E; ++I) { CGameGraph::CVertex &vertex = (*I).second->data(); VERIFY ((*I).second->edges().size() < 256); vertex.tNeighbourCount = (u8)(*I).second->edges().size(); vertex.dwEdgeOffset = edge_offset; edge_offset += vertex.tNeighbourCount*sizeof(CGameGraph::CEdge); writer.w (&vertex,sizeof(CGameGraph::CVertex)); } } { graph_type::const_vertex_iterator I = graph().vertices().begin(); graph_type::const_vertex_iterator E = graph().vertices().end(); for ( ; I != E; ++I) { graph_type::const_iterator i = (*I).second->edges().begin(); graph_type::const_iterator e = (*I).second->edges().end(); for ( ; i != e; ++i) { GameGraph::CEdge edge; VERIFY ((*i).vertex_id() < (u32(1) << (8*sizeof(GameGraph::_GRAPH_ID)))); edge.m_vertex_id = (GameGraph::_GRAPH_ID)(*i).vertex_id(); edge.m_path_distance = (*i).weight(); writer.w (&edge.m_vertex_id,sizeof(edge.m_vertex_id)); writer.w_float (edge.m_path_distance); } } } #ifdef PRIQUEL writer.save_to (m_graph_name); #else // PRIQUEL string_path file_name; strconcat (sizeof(file_name),file_name,*m_level_name,GAME_LEVEL_GRAPH); writer.save_to (file_name); #endif // PRIQUEL Msg ("%d bytes saved",int(writer.size())); Progress (start + amount); }