2022-02-27 03:15:00 +01:00
//=============================================================================//
//
// Purpose:
//
//=============================================================================//
# include "core/stdafx.h"
2022-03-22 01:59:02 +01:00
# include "tier0/fasttimer.h"
2022-04-09 16:16:40 +02:00
# include "tier1/cvar.h"
# include "tier1/cmd.h"
2022-03-22 01:59:02 +01:00
# include "mathlib/crc32.h"
# include "public/include/edict.h"
# include "public/include/utility.h"
2022-02-27 03:15:00 +01:00
# include "engine/host_state.h"
# include "engine/sys_utils.h"
# include "game/server/ai_node.h"
# include "game/server/ai_network.h"
# include "game/server/ai_networkmanager.h"
2022-03-22 17:18:29 +01:00
constexpr int AINET_SCRIPT_VERSION_NUMBER = 21 ;
constexpr int AINET_VERSION_NUMBER = 57 ;
2022-02-27 03:15:00 +01:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
CAI_NetworkBuilder : : BuildFile
Build AI node graph file from
in - memory structures and write
to disk to be loaded
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2022-03-22 01:59:02 +01:00
void CAI_NetworkBuilder : : SaveNetworkGraph ( CAI_Network * pNetwork )
2022-02-27 03:15:00 +01:00
{
2022-05-06 16:20:51 +02:00
string svMeshDir = " maps \\ navmesh \\ " ;
string svGraphDir = " maps \\ graphs \\ " ;
2022-03-22 01:59:02 +01:00
2022-05-06 16:20:51 +02:00
fs : : path fsMeshPath ( svMeshDir + g_pHostState - > m_levelName + " _ " + HULL_SIZE [ 3 ] + " .nm " ) ;
fs : : path fsGraphPath ( svGraphDir + g_pHostState - > m_levelName + " .ain " ) ;
2022-03-22 01:59:02 +01:00
CFastTimer masterTimer ;
CFastTimer timer ;
2022-03-21 00:28:14 +01:00
int nCalculatedLinkcount = 0 ;
2022-03-20 17:03:46 +01:00
2022-03-22 17:18:29 +01:00
// Build from memory.
2022-03-20 17:03:46 +01:00
DevMsg ( eDLL_T : : SERVER , " ++++--------------------------------------------------------------------------------------------------------------------------++++ \n " ) ;
DevMsg ( eDLL_T : : SERVER , " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> AI NETWORK GRAPH FILE CONSTRUCTION STARTED <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< \n " ) ;
DevMsg ( eDLL_T : : SERVER , " ++++--------------------------------------------------------------------------------------------------------------------------++++ \n " ) ;
2022-03-22 01:59:02 +01:00
DevMsg ( eDLL_T : : SERVER , " +- Writing header... \n " ) ;
masterTimer . Start ( ) ;
timer . Start ( ) ;
CreateDirectories ( svGraphDir ) ;
2022-03-20 17:03:46 +01:00
2022-05-06 16:20:51 +02:00
ofstream writeStream ( fsGraphPath , ofstream : : binary ) ;
2022-03-22 01:59:02 +01:00
DevMsg ( eDLL_T : : SERVER , " |-- AINet version: '%d' \n " , AINET_VERSION_NUMBER ) ;
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < const char * > ( & AINET_VERSION_NUMBER ) , sizeof ( int ) ) ;
2022-03-20 17:03:46 +01:00
int nMapVersion = g_ServerGlobalVariables - > m_nMapVersion ;
2022-03-22 01:59:02 +01:00
DevMsg ( eDLL_T : : SERVER , " |-- Map version: '%d' \n " , nMapVersion ) ;
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( & nMapVersion ) , sizeof ( int ) ) ;
2022-03-20 17:03:46 +01:00
2022-05-06 16:20:51 +02:00
ifstream iNavMesh ( fsMeshPath , fstream : : binary ) ;
vector < uint8_t > uNavMesh ;
uint32_t nNavMeshHash = NULL ;
2022-03-22 01:59:02 +01:00
if ( iNavMesh . good ( ) )
{
2022-05-06 16:20:51 +02:00
iNavMesh . seekg ( 0 , fstream : : end ) ;
2022-03-22 01:59:02 +01:00
uNavMesh . resize ( iNavMesh . tellg ( ) ) ;
2022-05-06 16:20:51 +02:00
iNavMesh . seekg ( 0 , fstream : : beg ) ;
2022-03-22 01:59:02 +01:00
iNavMesh . read ( ( char * ) uNavMesh . data ( ) , uNavMesh . size ( ) ) ;
nNavMeshHash = crc32 : : update ( NULL , uNavMesh . data ( ) , uNavMesh . size ( ) ) ;
}
else
{
2022-03-23 19:23:53 +01:00
Warning ( eDLL_T : : SERVER , " %s - No %s NavMesh found. Unable to calculate CRC for AI Network \n " , __FUNCTION__ , HULL_SIZE [ 3 ] . c_str ( ) ) ;
2022-03-22 01:59:02 +01:00
}
2022-03-22 17:18:29 +01:00
// Large NavMesh CRC.
2022-03-22 01:59:02 +01:00
DevMsg ( eDLL_T : : SERVER , " |-- NavMesh CRC: '%lx' \n " , nNavMeshHash ) ;
writeStream . write ( reinterpret_cast < const char * > ( & nNavMeshHash ) , sizeof ( int ) ) ;
2022-03-20 17:03:46 +01:00
2022-03-22 17:18:29 +01:00
// Path nodes.
2022-03-22 01:59:02 +01:00
DevMsg ( eDLL_T : : SERVER , " |-- Nodecount: '%d' \n " , pNetwork - > m_iNumNodes ) ;
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( & pNetwork - > m_iNumNodes ) , sizeof ( int ) ) ;
2022-03-20 17:03:46 +01:00
2022-03-22 01:59:02 +01:00
timer . End ( ) ;
DevMsg ( eDLL_T : : SERVER , " ...done writing header. %lf seconds \n " , timer . GetDuration ( ) . GetSeconds ( ) ) ;
timer . Start ( ) ;
DevMsg ( eDLL_T : : SERVER , " +- Writing node positions... \n " ) ;
2022-03-24 02:08:27 +01:00
if ( pNetwork - > m_pAInode )
2022-03-20 17:03:46 +01:00
{
2022-03-24 02:08:27 +01:00
for ( int i = 0 ; i < pNetwork - > m_iNumNodes ; i + + )
2022-03-20 17:03:46 +01:00
{
2022-03-24 02:08:27 +01:00
// Construct on-disk node struct.
CAI_NodeDisk diskNode { } ;
diskNode . m_vOrigin . x = pNetwork - > m_pAInode [ i ] - > m_vOrigin . x ;
diskNode . m_vOrigin . y = pNetwork - > m_pAInode [ i ] - > m_vOrigin . y ;
diskNode . m_vOrigin . z = pNetwork - > m_pAInode [ i ] - > m_vOrigin . z ;
diskNode . m_flYaw = pNetwork - > m_pAInode [ i ] - > m_flYaw ;
memcpy ( diskNode . hulls , pNetwork - > m_pAInode [ i ] - > m_fHulls , sizeof ( diskNode . hulls ) ) ;
diskNode . unk0 = static_cast < char > ( pNetwork - > m_pAInode [ i ] - > unk0 ) ;
diskNode . unk1 = pNetwork - > m_pAInode [ i ] - > unk1 ;
for ( int j = 0 ; j < MAX_HULLS ; j + + )
{
diskNode . unk2 [ j ] = static_cast < short > ( pNetwork - > m_pAInode [ i ] - > unk2 [ j ] ) ;
}
2022-03-20 17:03:46 +01:00
2022-03-24 02:08:27 +01:00
memcpy ( diskNode . unk3 , pNetwork - > m_pAInode [ i ] - > unk3 , sizeof ( diskNode . unk3 ) ) ;
diskNode . unk4 = pNetwork - > m_pAInode [ i ] - > unk6 ;
diskNode . unk5 = - 1 ; // aiNetwork->nodes[i]->unk8; // This field is wrong, however it's always -1 in original navmeshes anyway.
memcpy ( diskNode . unk6 , pNetwork - > m_pAInode [ i ] - > unk10 , sizeof ( diskNode . unk6 ) ) ;
2022-03-21 00:28:14 +01:00
2022-03-20 17:03:46 +01:00
2022-05-06 16:20:51 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Copying node '#%d' from '0x%p' to '0x%llX' \n " , pNetwork - > m_pAInode [ i ] - > m_nIndex , reinterpret_cast < void * > ( pNetwork - > m_pAInode [ i ] ) , static_cast < size_t > ( writeStream . tellp ( ) ) ) ;
2022-03-24 02:08:27 +01:00
writeStream . write ( reinterpret_cast < char * > ( & diskNode ) , sizeof ( CAI_NodeDisk ) ) ;
2022-03-20 17:03:46 +01:00
2022-03-24 02:08:27 +01:00
nCalculatedLinkcount + = pNetwork - > m_pAInode [ i ] - > m_nNumLinks ;
}
2022-03-20 17:03:46 +01:00
}
2022-03-22 01:59:02 +01:00
timer . End ( ) ;
DevMsg ( eDLL_T : : SERVER , " ...done writing node positions. %lf seconds \n " , timer . GetDuration ( ) . GetSeconds ( ) ) ;
timer . Start ( ) ;
DevMsg ( eDLL_T : : SERVER , " +- Writing links... \n " ) ;
2022-03-20 17:03:46 +01:00
2022-03-22 01:59:02 +01:00
DevMsg ( eDLL_T : : SERVER , " |-- Cache linkcount: '%d' \n " , pNetwork - > m_iNumLinks ) ;
DevMsg ( eDLL_T : : SERVER , " |-- Calculated linkcount: '%d' \n " , nCalculatedLinkcount ) ;
2022-03-20 17:03:46 +01:00
nCalculatedLinkcount / = 2 ;
2022-04-03 03:10:48 +02:00
if ( ai_ainDumpOnLoad - > GetBool ( ) )
2022-03-20 17:03:46 +01:00
{
2022-03-21 00:28:14 +01:00
if ( pNetwork - > m_iNumLinks ! = nCalculatedLinkcount )
2022-03-20 17:03:46 +01:00
{
2022-03-22 01:59:02 +01:00
Warning ( eDLL_T : : SERVER , " %s - Calculated linkcount '%d' doesn't match file linkcount '%d' (expected on build!) \n " , __FUNCTION__ , nCalculatedLinkcount , pNetwork - > m_iNumLinks ) ;
2022-03-20 17:03:46 +01:00
}
}
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( & nCalculatedLinkcount ) , sizeof ( int ) ) ;
2022-03-24 02:08:27 +01:00
if ( pNetwork - > m_pAInode )
2022-03-20 17:03:46 +01:00
{
2022-03-24 02:08:27 +01:00
for ( int i = 0 ; i < pNetwork - > m_iNumNodes ; i + + )
2022-03-20 17:03:46 +01:00
{
2022-03-24 02:08:27 +01:00
for ( int j = 0 ; j < pNetwork - > m_pAInode [ i ] - > m_nNumLinks ; j + + )
2022-03-22 01:59:02 +01:00
{
2022-03-24 02:08:27 +01:00
// Skip links that don't originate from current node.
if ( pNetwork - > m_pAInode [ i ] - > links [ j ] - > m_iSrcID ! = pNetwork - > m_pAInode [ i ] - > m_nIndex )
{
continue ;
}
CAI_NodeLinkDisk diskLink { } ;
diskLink . m_iSrcID = pNetwork - > m_pAInode [ i ] - > links [ j ] - > m_iSrcID ;
diskLink . m_iDestID = pNetwork - > m_pAInode [ i ] - > links [ j ] - > m_iDestID ;
diskLink . unk0 = pNetwork - > m_pAInode [ i ] - > links [ j ] - > unk1 ;
memcpy ( diskLink . m_bHulls , pNetwork - > m_pAInode [ i ] - > links [ j ] - > m_bHulls , sizeof ( diskLink . m_bHulls ) ) ;
2022-05-06 16:20:51 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing link '%d' => '%d' to '0x%llX' \n " , diskLink . m_iSrcID , diskLink . m_iDestID , static_cast < size_t > ( writeStream . tellp ( ) ) ) ;
2022-03-24 02:08:27 +01:00
writeStream . write ( reinterpret_cast < char * > ( & diskLink ) , sizeof ( CAI_NodeLinkDisk ) ) ;
2022-03-22 01:59:02 +01:00
}
2022-03-20 17:03:46 +01:00
}
}
2022-03-22 01:59:02 +01:00
timer . End ( ) ;
DevMsg ( eDLL_T : : SERVER , " ...done writing links. %lf seconds (%d links) \n " , timer . GetDuration ( ) . GetSeconds ( ) , nCalculatedLinkcount ) ;
timer . Start ( ) ;
DevMsg ( eDLL_T : : SERVER , " +- Writing hull data... \n " ) ;
2022-03-22 17:18:29 +01:00
// Don't know what this is, it's likely a block from tf1 that got deprecated? should just be 1 int per node.
2022-05-06 16:20:51 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing '%d' bytes for unknown block at '0x%llX' \n " , pNetwork - > m_iNumNodes * sizeof ( uint32_t ) , static_cast < size_t > ( writeStream . tellp ( ) ) ) ;
2022-03-22 17:18:29 +01:00
2022-03-24 16:31:53 +01:00
if ( static_cast < int > ( pNetwork - > m_iNumNodes ) > 0 )
2022-03-22 17:18:29 +01:00
{
2022-03-23 19:23:53 +01:00
uint32_t * unkNodeBlock = new uint32_t [ pNetwork - > m_iNumNodes ] ;
2022-03-22 17:18:29 +01:00
memset ( & unkNodeBlock , ' \0 ' , pNetwork - > m_iNumNodes * sizeof ( uint32_t ) ) ;
2022-03-23 19:23:53 +01:00
writeStream . write ( reinterpret_cast < char * > ( * unkNodeBlock ) , pNetwork - > m_iNumNodes * sizeof ( uint32_t ) ) ;
delete [ ] unkNodeBlock ;
2022-03-22 17:18:29 +01:00
}
// TODO: This is traverse nodes i think? these aren't used in r2 ains so we can get away with just writing count=0 and skipping
// but ideally should actually dump these.
2022-05-06 16:20:51 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing '%d' traversal nodes at '0x%llX' \n " , 0 , static_cast < size_t > ( writeStream . tellp ( ) ) ) ;
2022-03-22 17:18:29 +01:00
short traverseNodeCount = 0 ; // Only write count since count=0 means we don't have to actually do anything here.
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( & traverseNodeCount ) , sizeof ( short ) ) ;
2022-03-20 17:03:46 +01:00
2022-03-22 17:18:29 +01:00
// TODO: Ideally these should be actually dumped, but they're always 0 in r2 from what i can tell.
2022-05-06 16:20:51 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing '%d' bytes for unknown hull block at '0x%llX' \n " , MAX_HULLS * 8 , static_cast < size_t > ( writeStream . tellp ( ) ) ) ;
2022-03-20 17:03:46 +01:00
char * unkHullBlock = new char [ MAX_HULLS * 8 ] ;
2022-03-22 17:18:29 +01:00
memset ( unkHullBlock , ' \0 ' , MAX_HULLS * 8 ) ;
2022-03-20 17:03:46 +01:00
writeStream . write ( unkHullBlock , MAX_HULLS * 8 ) ;
delete [ ] unkHullBlock ;
2022-03-22 01:59:02 +01:00
timer . End ( ) ;
DevMsg ( eDLL_T : : SERVER , " ...done writing hull data. %lf seconds \n " , timer . GetDuration ( ) . GetSeconds ( ) ) ;
timer . Start ( ) ;
DevMsg ( eDLL_T : : SERVER , " +- Writing clusters... \n " ) ;
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( g_nAiNodeClusters ) , sizeof ( * g_nAiNodeClusters ) ) ;
2022-03-20 17:03:46 +01:00
for ( int i = 0 ; i < * g_nAiNodeClusters ; i + + )
{
2022-03-24 16:31:53 +01:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing cluster '#%d' at '0x%llx' \n " , i , static_cast < size_t > ( writeStream . tellp ( ) ) ) ;
2022-03-20 17:03:46 +01:00
AINodeClusters * nodeClusters = ( * g_pppAiNodeClusters ) [ i ] ;
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( & nodeClusters - > m_nIndex ) , sizeof ( nodeClusters - > m_nIndex ) ) ;
writeStream . write ( reinterpret_cast < char * > ( & nodeClusters - > unk1 ) , sizeof ( nodeClusters - > unk1 ) ) ;
2022-03-20 17:03:46 +01:00
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( & nodeClusters - > m_vOrigin . x ) , sizeof ( nodeClusters - > m_vOrigin . x ) ) ;
writeStream . write ( reinterpret_cast < char * > ( & nodeClusters - > m_vOrigin . y ) , sizeof ( nodeClusters - > m_vOrigin . y ) ) ;
writeStream . write ( reinterpret_cast < char * > ( & nodeClusters - > m_vOrigin . z ) , sizeof ( nodeClusters - > m_vOrigin . z ) ) ;
2022-03-20 17:03:46 +01:00
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( & nodeClusters - > unkcount0 ) , sizeof ( nodeClusters - > unkcount0 ) ) ;
2022-03-20 17:03:46 +01:00
for ( int j = 0 ; j < nodeClusters - > unkcount0 ; j + + )
{
2022-03-21 00:28:14 +01:00
short unk2Short = static_cast < short > ( nodeClusters - > unk2 [ j ] ) ;
writeStream . write ( reinterpret_cast < char * > ( & unk2Short ) , sizeof ( unk2Short ) ) ;
2022-03-20 17:03:46 +01:00
}
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( & nodeClusters - > unkcount1 ) , sizeof ( nodeClusters - > unkcount1 ) ) ;
2022-03-20 17:03:46 +01:00
for ( int j = 0 ; j < nodeClusters - > unkcount1 ; j + + )
{
2022-03-21 00:28:14 +01:00
short unk3Short = static_cast < short > ( nodeClusters - > unk3 [ j ] ) ;
writeStream . write ( reinterpret_cast < char * > ( & unk3Short ) , sizeof ( unk3Short ) ) ;
2022-03-20 17:03:46 +01:00
}
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( & nodeClusters - > unk5 ) , sizeof ( nodeClusters - > unk5 ) ) ;
2022-03-20 17:03:46 +01:00
}
2022-03-22 01:59:02 +01:00
timer . End ( ) ;
DevMsg ( eDLL_T : : SERVER , " ...done writing clusters. %lf seconds (%d clusters) \n " , timer . GetDuration ( ) . GetSeconds ( ) , * g_nAiNodeClusters ) ;
timer . Start ( ) ;
DevMsg ( eDLL_T : : SERVER , " +- Writing cluster links... \n " ) ;
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( g_nAiNodeClusterLinks ) , sizeof ( * g_nAiNodeClusterLinks ) ) ;
2022-03-20 17:03:46 +01:00
for ( int i = 0 ; i < * g_nAiNodeClusterLinks ; i + + )
{
// Disk and memory structs are literally identical here so just directly write.
2022-03-24 16:31:53 +01:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing cluster link '#%d' at '0x%llx' \n " , i , static_cast < size_t > ( writeStream . tellp ( ) ) ) ;
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( ( * g_pppAiNodeClusterLinks ) [ i ] ) , sizeof ( * ( * g_pppAiNodeClusterLinks ) [ i ] ) ) ;
2022-03-20 17:03:46 +01:00
}
2022-03-22 01:59:02 +01:00
timer . End ( ) ;
DevMsg ( eDLL_T : : SERVER , " ...done writing cluster links. %lf seconds (%d cluster links) \n " , timer . GetDuration ( ) . GetSeconds ( ) , * g_nAiNodeClusterLinks ) ;
// This is always set to '-1'. Likely a field for maintaining compatibility.
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( & pNetwork - > unk5 ) , sizeof ( pNetwork - > unk5 ) ) ;
2022-03-20 17:03:46 +01:00
2022-03-22 17:18:29 +01:00
// AIN v57 and above only (not present in r1, static array in r2, pointer to dynamic array in r5).
2022-03-22 01:59:02 +01:00
timer . Start ( ) ;
DevMsg ( eDLL_T : : SERVER , " +- Writing script nodes... \n " ) ;
2022-03-21 13:48:34 +01:00
writeStream . write ( reinterpret_cast < char * > ( & pNetwork - > m_iNumScriptNodes ) , sizeof ( pNetwork - > m_iNumScriptNodes ) ) ;
for ( int i = 0 ; i < pNetwork - > m_iNumScriptNodes ; i + + )
{
2022-03-22 17:18:29 +01:00
// Disk and memory structs for script nodes are identical.
2022-03-24 16:31:53 +01:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing script node '#%d' at '0x%llx' \n " , i , static_cast < size_t > ( writeStream . tellp ( ) ) ) ;
if ( ! IsBadReadPtrV2 ( reinterpret_cast < char * > ( & pNetwork - > m_ScriptNode [ i ] ) ) )
{
writeStream . write ( reinterpret_cast < char * > ( & pNetwork - > m_ScriptNode [ i ] ) , sizeof ( CAI_ScriptNode ) ) ;
}
else
{
Warning ( eDLL_T : : SERVER , " |-- Unable to write node '#%d' (invalid pointer) \n " , i , pNetwork - > m_iNumScriptNodes ) ;
}
2022-03-21 13:48:34 +01:00
}
2022-03-21 00:28:14 +01:00
2022-03-22 01:59:02 +01:00
timer . End ( ) ;
DevMsg ( eDLL_T : : SERVER , " ...done writing script nodes. %lf seconds (%d nodes) \n " , timer . GetDuration ( ) . GetSeconds ( ) , pNetwork - > m_iNumScriptNodes ) ;
timer . Start ( ) ;
DevMsg ( eDLL_T : : SERVER , " +- Writing hint data... \n " ) ;
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( & pNetwork - > m_iNumHints ) , sizeof ( pNetwork - > m_iNumHints ) ) ;
for ( int i = 0 ; i < pNetwork - > m_iNumHints ; i + + )
2022-03-20 17:03:46 +01:00
{
2022-03-24 16:31:53 +01:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing hint data '#%d' at '0x%llx' \n " , i , static_cast < size_t > ( writeStream . tellp ( ) ) ) ;
2022-03-21 00:28:14 +01:00
writeStream . write ( reinterpret_cast < char * > ( & pNetwork - > m_Hints [ i ] ) , sizeof ( pNetwork - > m_Hints [ i ] ) ) ;
2022-03-20 17:03:46 +01:00
}
2022-03-22 01:59:02 +01:00
timer . End ( ) ;
DevMsg ( eDLL_T : : SERVER , " ...done writing hint data. %lf seconds (%d hints) \n " , timer . GetDuration ( ) . GetSeconds ( ) , pNetwork - > m_iNumHints ) ;
masterTimer . End ( ) ;
DevMsg ( eDLL_T : : SERVER , " ...done writing AI node graph. %lf seconds \n " , masterTimer . GetDuration ( ) . GetSeconds ( ) ) ;
2022-03-21 00:28:14 +01:00
DevMsg ( eDLL_T : : SERVER , " ++++--------------------------------------------------------------------------------------------------------------------------++++ \n " ) ;
DevMsg ( eDLL_T : : SERVER , " ++++--------------------------------------------------------------------------------------------------------------------------++++ \n " ) ;
2022-03-20 17:03:46 +01:00
writeStream . close ( ) ;
2022-02-27 03:15:00 +01:00
}
2022-05-06 16:20:51 +02:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
CAI_NetworkManager : : LoadNetworkGraph
Load network from the disk
and validate status
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void CAI_NetworkManager : : LoadNetworkGraph ( CAI_NetworkManager * pAINetworkManager , void * pBuffer , const char * szAIGraphFile )
2022-02-27 03:15:00 +01:00
{
2022-05-06 16:20:51 +02:00
string svMeshDir = " maps \\ navmesh \\ " ;
string svGraphDir = " maps \\ graphs \\ " ;
fs : : path fsMeshPath ( svMeshDir + g_pHostState - > m_levelName + " _ " + HULL_SIZE [ 3 ] + " .nm " ) ;
fs : : path fsGraphPath ( svGraphDir + g_pHostState - > m_levelName + " .ain " ) ;
int nAiNetVersion = NULL ;
int nAiMapVersion = NULL ;
uint32_t nAiGraphHash = NULL ;
uint32_t nNavMeshHash = NULL ;
ifstream iAIGraph ( fsGraphPath , fstream : : binary ) ;
if ( iAIGraph . good ( ) )
{
iAIGraph . read ( reinterpret_cast < char * > ( & nAiNetVersion ) , sizeof ( int ) ) ;
iAIGraph . read ( reinterpret_cast < char * > ( & nAiMapVersion ) , sizeof ( int ) ) ;
iAIGraph . read ( reinterpret_cast < char * > ( & nAiGraphHash ) , sizeof ( uint32_t ) ) ;
if ( nAiNetVersion > AINET_VERSION_NUMBER )
{
Warning ( eDLL_T : : SERVER , " AI node graph '%s' deviates expectations (net version: '%d' expected: '%d') \n " ,
fsGraphPath . string ( ) . c_str ( ) , nAiNetVersion , AINET_VERSION_NUMBER ) ;
}
else if ( nAiMapVersion ! = g_ServerGlobalVariables - > m_nMapVersion )
{
Warning ( eDLL_T : : SERVER , " AI node graph '%s' is out of date (map version: '%d' expected: '%d') \n " ,
fsGraphPath . string ( ) . c_str ( ) , nAiMapVersion , g_ServerGlobalVariables - > m_nMapVersion ) ;
}
else
{
ifstream iNavMesh ( fsMeshPath , fstream : : binary ) ;
if ( iNavMesh . good ( ) )
{
vector < uint8_t > uNavMesh ;
iNavMesh . seekg ( 0 , fstream : : end ) ;
uNavMesh . resize ( iNavMesh . tellg ( ) ) ;
iNavMesh . seekg ( 0 , fstream : : beg ) ;
iNavMesh . read ( ( char * ) uNavMesh . data ( ) , uNavMesh . size ( ) ) ;
nNavMeshHash = crc32 : : update ( NULL , uNavMesh . data ( ) , uNavMesh . size ( ) ) ;
if ( nNavMeshHash ! = nAiGraphHash )
{
Warning ( eDLL_T : : SERVER , " AI node graph '%s' is out of date (%s NavMesh checksum: '0x%X' expected: '0x%X') \n " ,
fsGraphPath . string ( ) . c_str ( ) , HULL_SIZE [ 3 ] . c_str ( ) , nNavMeshHash , nAiGraphHash ) ;
}
iNavMesh . close ( ) ;
}
}
iAIGraph . close ( ) ;
}
2022-03-07 11:36:45 +01:00
# if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
2022-05-06 16:20:51 +02:00
CAI_NetworkManager__LoadNetworkGraph ( pAINetworkManager , pBuffer , szAIGraphFile , NULL ) ;
2022-03-07 11:36:45 +01:00
# elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
2022-05-06 16:20:51 +02:00
CAI_NetworkManager__LoadNetworkGraph ( pAINetworkManager , pBuffer , szAIGraphFile ) ;
2022-03-07 11:36:45 +01:00
# endif
2022-02-27 03:15:00 +01:00
2022-04-03 03:10:48 +02:00
if ( ai_ainDumpOnLoad - > GetBool ( ) )
2022-02-27 03:15:00 +01:00
{
2022-05-06 16:20:51 +02:00
DevMsg ( eDLL_T : : SERVER , " Running BuildAINFile for loaded AI node graph '%s' \n " , szAIGraphFile ) ;
CAI_NetworkBuilder : : SaveNetworkGraph ( * ( CAI_Network * * ) ( reinterpret_cast < char * > ( pAINetworkManager ) + AINETWORK_OFFSET ) ) ;
2022-02-27 03:15:00 +01:00
}
}
2022-05-06 16:20:51 +02:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
CAI_NetworkBuilder : : Build
builds network in - memory
during level load
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void CAI_NetworkBuilder : : Build ( CAI_NetworkBuilder * pBuilder , CAI_Network * pAINetwork , void * a3 , int a4 )
2022-02-27 03:15:00 +01:00
{
2022-05-06 16:20:51 +02:00
CAI_NetworkBuilder__Build ( pBuilder , pAINetwork , a3 , a4 ) ;
CAI_NetworkBuilder : : SaveNetworkGraph ( pAINetwork ) ;
2022-02-27 03:15:00 +01:00
}
void CAI_NetworkManager_Attach ( )
{
2022-05-06 16:20:51 +02:00
DetourAttach ( ( LPVOID * ) & CAI_NetworkManager__LoadNetworkGraph , & CAI_NetworkManager : : LoadNetworkGraph ) ;
DetourAttach ( ( LPVOID * ) & CAI_NetworkBuilder__Build , & CAI_NetworkBuilder : : Build ) ;
2022-02-27 03:15:00 +01:00
}
void CAI_NetworkManager_Detach ( )
{
2022-05-06 16:20:51 +02:00
DetourDetach ( ( LPVOID * ) & CAI_NetworkManager__LoadNetworkGraph , & CAI_NetworkManager : : LoadNetworkGraph ) ;
DetourDetach ( ( LPVOID * ) & CAI_NetworkBuilder__Build , & CAI_NetworkBuilder : : Build ) ;
2022-02-27 03:15:00 +01:00
}