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"
2022-08-09 17:18:07 +02:00
# include "public/edict.h"
# include "public/utility/utility.h"
2022-08-23 21:32:12 +02:00
# include "filesystem/filesystem.h"
2022-02-27 03:15:00 +01:00
# include "engine/host_state.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-08-23 21:32:12 +02:00
constexpr int AINETWORK_MIN_SIZE = 82 ;
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-08-23 21:32:12 +02:00
const string svMeshDir = " maps/navmesh/ " ;
const string svGraphDir = " maps/graphs/ " ;
2022-03-22 01:59:02 +01:00
2022-08-11 11:07:45 +02:00
fs : : path fsMeshPath ( svMeshDir + g_pHostState - > m_levelName + " _ " + SHULL_SIZE [ EHULL_SIZE : : LARGE ] + " .nm " ) ;
2022-05-06 16:20:51 +02:00
fs : : path fsGraphPath ( svGraphDir + g_pHostState - > m_levelName + " .ain " ) ;
2022-03-22 01:59:02 +01:00
CFastTimer masterTimer ;
CFastTimer timer ;
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
masterTimer . Start ( ) ;
timer . Start ( ) ;
2022-08-23 21:32:12 +02:00
FileHandle_t pAIGraph = FileSystem ( ) - > Open ( fsGraphPath . relative_path ( ) . u8string ( ) . c_str ( ) , " wb " , " GAME " ) ;
if ( ! pAIGraph )
{
Error ( eDLL_T : : SERVER , false , " %s - Unable to write to '%s' (read-only?) \n " , __FUNCTION__ , fsGraphPath . relative_path ( ) . u8string ( ) . c_str ( ) ) ;
return ;
}
2022-03-20 17:03:46 +01:00
2022-08-23 21:32:12 +02:00
DevMsg ( eDLL_T : : SERVER , " +- Writing header... \n " ) ;
2022-03-22 01:59:02 +01:00
DevMsg ( eDLL_T : : SERVER , " |-- AINet version: '%d' \n " , AINET_VERSION_NUMBER ) ;
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & AINET_VERSION_NUMBER , sizeof ( int ) , pAIGraph ) ;
2022-03-20 17:03:46 +01:00
2022-06-24 16:56:28 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Map version: '%d' \n " , g_ServerGlobalVariables - > m_nMapVersion ) ;
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & g_ServerGlobalVariables - > m_nMapVersion , sizeof ( int ) , pAIGraph ) ;
2022-03-20 17:03:46 +01:00
2022-08-23 21:32:12 +02:00
FileHandle_t pNavMesh = FileSystem ( ) - > Open ( fsMeshPath . relative_path ( ) . u8string ( ) . c_str ( ) , " rb " , " GAME " ) ;
2022-05-06 16:20:51 +02:00
uint32_t nNavMeshHash = NULL ;
2022-08-23 21:32:12 +02:00
if ( ! pNavMesh )
2022-03-22 01:59:02 +01:00
{
2022-08-23 21:32:12 +02:00
Warning ( eDLL_T : : SERVER , " %s - No %s NavMesh found. Unable to calculate CRC for AI Network. \n " , __FUNCTION__ , SHULL_SIZE [ EHULL_SIZE : : LARGE ] . c_str ( ) ) ;
2022-03-22 01:59:02 +01:00
}
else
{
2022-08-23 21:32:12 +02:00
uint32_t nLen = FileSystem ( ) - > Size ( pNavMesh ) ;
uint8_t * pBuf = MemAllocSingleton ( ) - > Alloc < uint8_t > ( nLen ) ;
FileSystem ( ) - > Read ( pBuf , nLen , pNavMesh ) ;
FileSystem ( ) - > Close ( pNavMesh ) ;
nNavMeshHash = crc32 : : update ( NULL , pBuf , nLen ) ;
MemAllocSingleton ( ) - > Free ( pBuf ) ;
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 ) ;
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & nNavMeshHash , sizeof ( uint32_t ) , pAIGraph ) ;
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-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & pNetwork - > m_iNumNodes , sizeof ( int ) , pAIGraph ) ;
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
2022-08-23 21:32:12 +02:00
int nCalculatedLinkcount = 0 ;
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-08-23 21:32:12 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Copying node '#%d' from '0x%p' to '0x%zX' \n " , pNetwork - > m_pAInode [ i ] - > m_nIndex , reinterpret_cast < void * > ( pNetwork - > m_pAInode [ i ] ) , FileSystem ( ) - > Tell ( pAIGraph ) ) ;
FileSystem ( ) - > Write ( & diskNode , sizeof ( CAI_NodeDisk ) , pAIGraph ) ;
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-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & nCalculatedLinkcount , sizeof ( int ) , pAIGraph ) ;
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-08-23 21:32:12 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing link '%h' => '%h' to '0x%zX' \n " , diskLink . m_iSrcID , diskLink . m_iDestID , FileSystem ( ) - > Tell ( pAIGraph ) ) ;
FileSystem ( ) - > Write ( & diskLink , sizeof ( CAI_NodeLinkDisk ) , pAIGraph ) ;
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-08-23 21:32:12 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing '%d' bytes for node block at '0x%zX' \n " , pNetwork - > m_iNumNodes * sizeof ( uint32_t ) , FileSystem ( ) - > Tell ( pAIGraph ) ) ;
2022-03-22 17:18:29 +01:00
2022-08-11 11:07:45 +02:00
if ( pNetwork - > m_iNumNodes > 0 )
2022-03-22 17:18:29 +01:00
{
2022-08-23 21:32:12 +02:00
uint32_t * unkNodeBlock = MemAllocSingleton ( ) - > Alloc < uint32_t > ( pNetwork - > m_iNumNodes * sizeof ( uint32_t ) ) ;
2022-03-22 17:18:29 +01:00
memset ( & unkNodeBlock , ' \0 ' , pNetwork - > m_iNumNodes * sizeof ( uint32_t ) ) ;
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & * unkNodeBlock , pNetwork - > m_iNumNodes * sizeof ( uint32_t ) , pAIGraph ) ;
MemAllocSingleton ( ) - > Free ( 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-08-23 21:32:12 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing '%d' traversal nodes at '0x%zX' \n " , 0 , FileSystem ( ) - > Tell ( pAIGraph ) ) ;
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-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & traverseNodeCount , sizeof ( short ) , pAIGraph ) ;
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-08-23 21:32:12 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing '%d' bytes for hull data block at '0x%zX' \n " , MAX_HULLS * 8 , FileSystem ( ) - > Tell ( pAIGraph ) ) ;
2022-07-20 21:06:19 +02:00
for ( int i = 0 ; i < ( MAX_HULLS * 8 ) ; i + + )
{
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( " \0 " , sizeof ( char ) , pAIGraph ) ;
2022-07-20 21:06:19 +02: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 hull data. %lf seconds \n " , timer . GetDuration ( ) . GetSeconds ( ) ) ;
timer . Start ( ) ;
DevMsg ( eDLL_T : : SERVER , " +- Writing clusters... \n " ) ;
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & * g_nAiNodeClusters , sizeof ( * g_nAiNodeClusters ) , pAIGraph ) ;
2022-03-20 17:03:46 +01:00
for ( int i = 0 ; i < * g_nAiNodeClusters ; i + + )
{
2022-08-23 21:32:12 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing cluster '#%d' at '0x%zX' \n " , i , FileSystem ( ) - > Tell ( pAIGraph ) ) ;
2022-03-20 17:03:46 +01:00
AINodeClusters * nodeClusters = ( * g_pppAiNodeClusters ) [ i ] ;
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & nodeClusters - > m_nIndex , sizeof ( nodeClusters - > m_nIndex ) , pAIGraph ) ;
FileSystem ( ) - > Write ( & nodeClusters - > unk1 , sizeof ( nodeClusters - > unk1 ) , pAIGraph ) ;
2022-03-20 17:03:46 +01:00
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & nodeClusters - > m_vOrigin . x , sizeof ( nodeClusters - > m_vOrigin . x ) , pAIGraph ) ;
FileSystem ( ) - > Write ( & nodeClusters - > m_vOrigin . y , sizeof ( nodeClusters - > m_vOrigin . y ) , pAIGraph ) ;
FileSystem ( ) - > Write ( & nodeClusters - > m_vOrigin . z , sizeof ( nodeClusters - > m_vOrigin . z ) , pAIGraph ) ;
2022-03-20 17:03:46 +01:00
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & nodeClusters - > unkcount0 , sizeof ( nodeClusters - > unkcount0 ) , pAIGraph ) ;
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 ] ) ;
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & unk2Short , sizeof ( unk2Short ) , pAIGraph ) ;
2022-03-20 17:03:46 +01:00
}
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & nodeClusters - > unkcount1 , sizeof ( nodeClusters - > unkcount1 ) , pAIGraph ) ;
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 ] ) ;
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & unk3Short , sizeof ( unk3Short ) , pAIGraph ) ;
2022-03-20 17:03:46 +01:00
}
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & nodeClusters - > unk5 , sizeof ( nodeClusters - > unk5 ) , pAIGraph ) ;
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-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & * g_nAiNodeClusterLinks , sizeof ( * g_nAiNodeClusterLinks ) , pAIGraph ) ;
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-08-23 21:32:12 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing cluster link '#%d' at '0x%zX' \n " , i , FileSystem ( ) - > Tell ( pAIGraph ) ) ;
FileSystem ( ) - > Write ( & * g_pppAiNodeClusterLinks [ i ] , sizeof ( * ( * g_pppAiNodeClusterLinks ) [ i ] ) , pAIGraph ) ;
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-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & pNetwork - > unk5 , sizeof ( pNetwork - > unk5 ) , pAIGraph ) ;
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-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & pNetwork - > m_iNumScriptNodes , sizeof ( pNetwork - > m_iNumScriptNodes ) , pAIGraph ) ;
2022-03-21 13:48:34 +01:00
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-08-23 21:32:12 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing script node '#%d' at '0x%zX' \n " , i , FileSystem ( ) - > Tell ( pAIGraph ) ) ;
FileSystem ( ) - > Write ( & pNetwork - > m_ScriptNode [ i ] , sizeof ( CAI_ScriptNode ) , pAIGraph ) ;
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-08-23 21:32:12 +02:00
FileSystem ( ) - > Write ( & pNetwork - > m_iNumHints , sizeof ( pNetwork - > m_iNumHints ) , pAIGraph ) ;
2022-03-21 00:28:14 +01:00
for ( int i = 0 ; i < pNetwork - > m_iNumHints ; i + + )
2022-03-20 17:03:46 +01:00
{
2022-08-23 21:32:12 +02:00
DevMsg ( eDLL_T : : SERVER , " |-- Writing hint data '#%d' at '0x%zX' \n " , i , FileSystem ( ) - > Tell ( pAIGraph ) ) ;
FileSystem ( ) - > Write ( & pNetwork - > m_Hints [ i ] , sizeof ( pNetwork - > m_Hints [ i ] ) , pAIGraph ) ;
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 ) ;
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Close ( pAIGraph ) ;
2022-03-22 01:59:02 +01:00
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-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-08-23 21:32:12 +02:00
string svMeshDir = " maps/navmesh/ " ;
string svGraphDir = " maps/graphs/ " ;
2022-05-06 16:20:51 +02:00
2022-08-11 11:07:45 +02:00
fs : : path fsMeshPath ( svMeshDir + g_pHostState - > m_levelName + " _ " + SHULL_SIZE [ EHULL_SIZE : : LARGE ] + " .nm " ) ;
2022-05-06 16:20:51 +02:00
fs : : path fsGraphPath ( svGraphDir + g_pHostState - > m_levelName + " .ain " ) ;
int nAiNetVersion = NULL ;
int nAiMapVersion = NULL ;
2022-08-23 21:32:12 +02:00
bool bNavMeshAvailable = true ;
2022-05-06 16:20:51 +02:00
uint32_t nAiGraphHash = NULL ;
uint32_t nNavMeshHash = NULL ;
2022-08-23 21:32:12 +02:00
FileHandle_t pNavMesh = FileSystem ( ) - > Open ( fsMeshPath . relative_path ( ) . u8string ( ) . c_str ( ) , " rb " , " GAME " ) ;
if ( ! pNavMesh )
{
Warning ( eDLL_T : : SERVER , " %s - No %s NavMesh found. Unable to calculate CRC for AI Network. \n " , __FUNCTION__ , SHULL_SIZE [ EHULL_SIZE : : LARGE ] . c_str ( ) ) ;
bNavMeshAvailable = false ;
}
else
{
uint32_t nLen = FileSystem ( ) - > Size ( pNavMesh ) ;
uint8_t * pBuf = MemAllocSingleton ( ) - > Alloc < uint8_t > ( nLen ) ;
FileSystem ( ) - > Read ( pBuf , nLen , pNavMesh ) ;
FileSystem ( ) - > Close ( pNavMesh ) ;
nNavMeshHash = crc32 : : update ( NULL , pBuf , nLen ) ;
MemAllocSingleton ( ) - > Free ( pBuf ) ;
}
FileHandle_t pAIGraph = FileSystem ( ) - > Open ( fsGraphPath . relative_path ( ) . u8string ( ) . c_str ( ) , " rb " , " GAME " ) ;
if ( ! pAIGraph )
{
Error ( eDLL_T : : SERVER , false , " %s - Unable to open '%s' (insufficient rights?) \n " , __FUNCTION__ ,
fsGraphPath . relative_path ( ) . u8string ( ) . c_str ( ) ) ;
LoadNetworkGraphEx ( pAINetworkManager , pBuffer , szAIGraphFile ) ;
2022-08-11 12:09:38 +02:00
2022-08-23 21:32:12 +02:00
return ;
}
if ( FileSystem ( ) - > Size ( pAIGraph ) > = AINETWORK_MIN_SIZE )
2022-05-06 16:20:51 +02:00
{
2022-08-23 21:32:12 +02:00
FileSystem ( ) - > Read ( & nAiNetVersion , sizeof ( int ) , pAIGraph ) ;
FileSystem ( ) - > Read ( & nAiMapVersion , sizeof ( int ) , pAIGraph ) ;
FileSystem ( ) - > Read ( & nAiGraphHash , sizeof ( int ) , pAIGraph ) ;
2022-05-06 16:20:51 +02:00
if ( nAiNetVersion > AINET_VERSION_NUMBER )
{
2022-08-23 21:32:12 +02:00
Warning ( eDLL_T : : SERVER , " AI node graph '%s' deviates expectations (net version: '%d' expected: '%d') \n " ,
2022-08-09 15:19:12 +02:00
fsGraphPath . relative_path ( ) . u8string ( ) . c_str ( ) , nAiNetVersion , AINET_VERSION_NUMBER ) ;
2022-05-06 16:20:51 +02:00
}
else if ( nAiMapVersion ! = g_ServerGlobalVariables - > m_nMapVersion )
{
2022-08-23 21:32:12 +02:00
Warning ( eDLL_T : : SERVER , " AI node graph '%s' is out of date (map version: '%d' expected: '%d') \n " ,
2022-08-09 15:19:12 +02:00
fsGraphPath . relative_path ( ) . u8string ( ) . c_str ( ) , nAiMapVersion , g_ServerGlobalVariables - > m_nMapVersion ) ;
2022-05-06 16:20:51 +02:00
}
else
{
2022-08-23 21:32:12 +02:00
if ( bNavMeshAvailable )
2022-08-11 12:09:38 +02:00
{
2022-05-06 16:20:51 +02:00
if ( nNavMeshHash ! = nAiGraphHash )
{
2022-05-09 02:20:07 +02:00
Warning ( eDLL_T : : SERVER , " AI node graph '%s' is out of date (checksum: '0x%X' expected: '0x%X') \n " ,
2022-08-09 15:19:12 +02:00
fsGraphPath . relative_path ( ) . u8string ( ) . c_str ( ) , nNavMeshHash , nAiGraphHash ) ;
2022-05-06 16:20:51 +02:00
}
}
}
}
2022-08-23 21:32:12 +02:00
else
{
Error ( eDLL_T : : SERVER , false , " %s - AI node graph '%s' is corrupt (LEN_BYTES < AINETWORK_MIN_SIZE) \n " , __FUNCTION__ ,
fsGraphPath . relative_path ( ) . u8string ( ) . c_str ( ) ) ;
}
FileSystem ( ) - > Close ( pAIGraph ) ;
LoadNetworkGraphEx ( pAINetworkManager , pBuffer , szAIGraphFile ) ;
}
2022-05-06 16:20:51 +02:00
2022-08-23 21:32:12 +02:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
CAI_NetworkManager : : LoadNetworkGraphEx
Load network
( internal )
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void CAI_NetworkManager : : LoadNetworkGraphEx ( CAI_NetworkManager * pAINetworkManager , void * pBuffer , const char * szAIGraphFile )
{
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
}