Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2548 lines
65 KiB

  1. //===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $NoKeywords: $
  7. //===========================================================================//
  8. #include "server_pch.h"
  9. #include <algorithm>
  10. #include "vengineserver_impl.h"
  11. #include "vox.h"
  12. #include "sound.h"
  13. #include "gl_model_private.h"
  14. #include "host_saverestore.h"
  15. #include "world.h"
  16. #include "l_studio.h"
  17. #include "decal.h"
  18. #include "sys_dll.h"
  19. #include "sv_log.h"
  20. #include "sv_main.h"
  21. #include "tier1/strtools.h"
  22. #include "collisionutils.h"
  23. #include "staticpropmgr.h"
  24. #include "string_t.h"
  25. #include "vstdlib/random.h"
  26. #include "EngineSoundInternal.h"
  27. #include "dt_send_eng.h"
  28. #include "PlayerState.h"
  29. #include "irecipientfilter.h"
  30. #include "sv_user.h"
  31. #include "server_class.h"
  32. #include "cdll_engine_int.h"
  33. #include "enginesingleuserfilter.h"
  34. #include "ispatialpartitioninternal.h"
  35. #include "con_nprint.h"
  36. #include "tmessage.h"
  37. #include "iscratchpad3d.h"
  38. #include "pr_edict.h"
  39. #include "networkstringtableserver.h"
  40. #include "networkstringtable.h"
  41. #include "LocalNetworkBackdoor.h"
  42. #include "host_phonehome.h"
  43. #include "sv_plugin.h"
  44. #include "singleplayersharedmemory.h"
  45. #include "MapReslistGenerator.h"
  46. #include "sv_steamauth.h"
  47. #include "LoadScreenUpdate.h"
  48. #include "paint.h"
  49. #include "matchmaking/imatchframework.h"
  50. #include "r_decal.h"
  51. #include "igame.h"
  52. #include "sv_packedentities.h"
  53. #include "hltvserver.h"
  54. // memdbgon must be the last include file in a .cpp file!!!
  55. #include "tier0/memdbgon.h"
  56. #define MAX_MESSAGE_SIZE 2500
  57. #define MAX_TOTAL_ENT_LEAFS 128
  58. void SV_DetermineMulticastRecipients( bool usepas, const Vector& origin, CPlayerBitVec& playerbits );
  59. void DecalRemove( const model_t *model, const Vector& origin, float radius );
  60. extern CNetworkStringTableContainer *networkStringTableContainerServer;
  61. extern ConVar host_timescale;
  62. CSharedEdictChangeInfo g_SharedEdictChangeInfo;
  63. CSharedEdictChangeInfo *g_pSharedChangeInfo = &g_SharedEdictChangeInfo;
  64. IAchievementMgr *g_pAchievementMgr = NULL;
  65. CGamestatsData *g_pGamestatsData = NULL;
  66. static ConVar sv_show_usermessage( "sv_show_usermessage", "0", 0, "Shows the user messages that the server is sending to clients. Setting this to 2 will show the contents of the message");
  67. void InvalidateSharedEdictChangeInfos()
  68. {
  69. if ( g_SharedEdictChangeInfo.m_iSerialNumber == 0xFFFF )
  70. {
  71. // Reset all edicts to 0.
  72. g_SharedEdictChangeInfo.m_iSerialNumber = 1;
  73. for ( int i=0; i < sv.num_edicts; i++ )
  74. {
  75. //if the edict has any changes, force a full state change (which will release the change info)
  76. if( sv.edicts[i].HasStateChanged() )
  77. sv.edicts[i].StateChanged();
  78. }
  79. }
  80. else
  81. {
  82. g_SharedEdictChangeInfo.m_iSerialNumber++;
  83. }
  84. g_SharedEdictChangeInfo.m_nChangeInfos = 0;
  85. }
  86. // ---------------------------------------------------------------------- //
  87. // Globals.
  88. // ---------------------------------------------------------------------- //
  89. struct MsgData
  90. {
  91. MsgData()
  92. {
  93. Reset();
  94. // link buffers to messages
  95. m_DataOut.StartWriting( entitydata, sizeof(entitydata) );
  96. m_DataOut.SetDebugName( "s_MsgData.entityMsg.m_DataOut" );
  97. }
  98. void Reset()
  99. {
  100. filter = NULL;
  101. reliable = false;
  102. started = false;
  103. entityMsg.Clear();
  104. }
  105. byte entitydata[ PAD_NUMBER( MAX_ENTITY_MSG_DATA, 4 ) ]; // buffer for outgoing entity messages
  106. IRecipientFilter *filter; // clients who get this message
  107. bool reliable;
  108. bool started; // IS THERE A MESSAGE IN THE PROCESS OF BEING SENT?
  109. CSVCMsg_EntityMsg_t entityMsg;
  110. bf_write m_DataOut;
  111. };
  112. static MsgData s_MsgData;
  113. void SeedRandomNumberGenerator( bool random_invariant )
  114. {
  115. if (!random_invariant)
  116. {
  117. int iSeed = -(long)Sys_FloatTime();
  118. if (1000 < iSeed)
  119. {
  120. iSeed = -iSeed;
  121. }
  122. else if (-1000 < iSeed)
  123. {
  124. iSeed -= 22261048;
  125. }
  126. RandomSeed( iSeed );
  127. }
  128. else
  129. {
  130. // Make those random numbers the same every time!
  131. RandomSeed( 0 );
  132. }
  133. }
  134. // ---------------------------------------------------------------------- //
  135. // Static helpers.
  136. // ---------------------------------------------------------------------- //
  137. static void PR_CheckEmptyString (const char *s)
  138. {
  139. if (s[0] <= ' ')
  140. Host_Error ("Bad string: %s", s);
  141. }
  142. // Average a list a vertices to find an approximate "center"
  143. static void CenterVerts( Vector verts[], int vertCount, Vector& center )
  144. {
  145. int i;
  146. float scale;
  147. if ( vertCount )
  148. {
  149. Vector edge0, edge1, normal;
  150. VectorCopy( vec3_origin, center );
  151. // sum up verts
  152. for ( i = 0; i < vertCount; i++ )
  153. {
  154. VectorAdd( center, verts[i], center );
  155. }
  156. scale = 1.0f / (float)vertCount;
  157. VectorScale( center, scale, center ); // divide by vertCount
  158. // Compute 2 poly edges
  159. VectorSubtract( verts[1], verts[0], edge0 );
  160. VectorSubtract( verts[vertCount-1], verts[0], edge1 );
  161. // cross for normal
  162. CrossProduct( edge0, edge1, normal );
  163. // Find the component of center that is outside of the plane
  164. scale = DotProduct( center, normal ) - DotProduct( verts[0], normal );
  165. // subtract it off
  166. VectorMA( center, scale, normal, center );
  167. // center is in the plane now
  168. }
  169. }
  170. // Copy the list of verts from an msurface_t int a linear array
  171. static void SurfaceToVerts( model_t *model, SurfaceHandle_t surfID, Vector verts[], int *vertCount )
  172. {
  173. if ( *vertCount > MSurf_VertCount( surfID ) )
  174. *vertCount = MSurf_VertCount( surfID );
  175. // Build the list of verts from 0 to n
  176. for ( int i = 0; i < *vertCount; i++ )
  177. {
  178. int vertIndex = model->brush.pShared->vertindices[ MSurf_FirstVertIndex( surfID ) + i ];
  179. Vector& vert = model->brush.pShared->vertexes[ vertIndex ].position;
  180. VectorCopy( vert, verts[i] );
  181. }
  182. // vert[0] is the first and last vert, there is no copy
  183. }
  184. // Calculate the surface area of an arbitrary msurface_t polygon (convex with collinear verts)
  185. static float SurfaceArea( model_t *model, SurfaceHandle_t surfID )
  186. {
  187. Vector center, verts[32];
  188. int vertCount = 32;
  189. float area;
  190. int i;
  191. // Compute a "center" point and fan
  192. SurfaceToVerts( model, surfID, verts, &vertCount );
  193. CenterVerts( verts, vertCount, center );
  194. area = 0;
  195. // For a triangle of the center and each edge
  196. for ( i = 0; i < vertCount; i++ )
  197. {
  198. Vector edge0, edge1, out;
  199. int next;
  200. next = (i+1)%vertCount;
  201. VectorSubtract( verts[i], center, edge0 ); // 0.5 * edge cross edge (0.5 is done once at the end)
  202. VectorSubtract( verts[next], center, edge1 );
  203. CrossProduct( edge0, edge1, out );
  204. area += VectorLength( out );
  205. }
  206. return area * 0.5; // 0.5 here
  207. }
  208. // Average the list of vertices to find an approximate "center"
  209. static void SurfaceCenter( model_t *model, SurfaceHandle_t surfID, Vector& center )
  210. {
  211. Vector verts[32]; // We limit faces to 32 verts elsewhere in the engine
  212. int vertCount = 32;
  213. SurfaceToVerts( model, surfID, verts, &vertCount );
  214. CenterVerts( verts, vertCount, center );
  215. }
  216. static bool ValidCmd( const char *pCmd )
  217. {
  218. int len;
  219. len = strlen(pCmd);
  220. // Valid commands all have a ';' or newline '\n' as their last character
  221. if ( len && (pCmd[len-1] == '\n' || pCmd[len-1] == ';') )
  222. return true;
  223. return false;
  224. }
  225. //
  226. // HLTV relay proxy whitelist
  227. //
  228. struct HltvRelayProxyWhitelistMask_t
  229. {
  230. uint32 a, b, c, d;
  231. uint32 numbits;
  232. bool operator==( HltvRelayProxyWhitelistMask_t const &other ) const
  233. {
  234. return 0 == Q_memcmp( this, &other, sizeof( *this ) );
  235. }
  236. };
  237. static CUtlVector< HltvRelayProxyWhitelistMask_t > s_arrHltvRelayProxyWhitelist;
  238. bool IsHltvRelayProxyWhitelisted( ns_address const &adr )
  239. {
  240. if ( !adr.IsType<netadr_t>() )
  241. return false;
  242. uint32 uiServerIP = adr.AsType<netadr_t>().GetIPHostByteOrder();
  243. #define MAKE_IP_MASK( a, b, c, d, numbits ) ( uint32( ( (uint32(a)&0xFF) << 24 ) | ( (uint32(b)&0xFF) << 16 ) | ( (uint32(c)&0xFF) << 8 ) | ( (uint32(d)&0xFF) ) ) & ( (~0u) << (32-numbits) ) )
  244. #define IPRANGEENTRY( a, b, c, d, numbits ) if ( ( uiServerIP & ( (~0u) << (32-numbits) ) ) == MAKE_IP_MASK( a, b, c, d, numbits ) ) return true;
  245. FOR_EACH_VEC( s_arrHltvRelayProxyWhitelist, idx )
  246. {
  247. HltvRelayProxyWhitelistMask_t const &e = s_arrHltvRelayProxyWhitelist[idx];
  248. IPRANGEENTRY( e.a, e.b, e.c, e.d, e.numbits );
  249. }
  250. #undef IPRANGEENTRY
  251. #undef MAKE_IP_MASK
  252. return false;
  253. }
  254. // ---------------------------------------------------------------------- //
  255. // CVEngineServer
  256. // ---------------------------------------------------------------------- //
  257. class CVEngineServer : public IVEngineServer
  258. {
  259. public:
  260. virtual void ChangeLevel( const char* s1, const char* s2)
  261. {
  262. static int last_spawncount;
  263. // make sure we don't issue two changelevels
  264. if (sv.GetSpawnCount() == last_spawncount)
  265. return;
  266. last_spawncount = sv.GetSpawnCount();
  267. if ( !s1 )
  268. {
  269. Sys_Error( "CVEngineServer::Changelevel with NULL s1\n" );
  270. }
  271. char cmd[ 256 ];
  272. if ( !s2 ) // no indication of where they are coming from; so just do a standard old changelevel
  273. {
  274. Q_snprintf( cmd, sizeof( cmd ), "changelevel %s\n", s1 );
  275. }
  276. else
  277. {
  278. Q_snprintf( cmd, sizeof( cmd ), "changelevel2 %s %s\n", s1, s2 );
  279. }
  280. Cbuf_AddText( CBUF_SERVER, cmd );
  281. }
  282. virtual int IsMapValid( const char *filename )
  283. {
  284. return modelloader->Map_IsValid( filename );
  285. }
  286. virtual bool IsDedicatedServer( void )
  287. {
  288. return sv.IsDedicated();
  289. }
  290. virtual int GetLocalClientIndex( void )
  291. {
  292. #ifndef DEDICATED
  293. if ( sv.IsDedicated() )
  294. {
  295. return 0; // this query really makes no sense on a dedicated server, but we can agree that "local client" means "the person typing at the text console"
  296. }
  297. else
  298. {
  299. // return splitscreen->IsLocalPlayerResolvable() ? GetLocalClient().m_nPlayerSlot : GetBaseLocalClient().m_nPlayerSlot; // this is the same check as in Cmd_ExecuteCommand()
  300. return GetBaseLocalClient().m_nPlayerSlot + 1; // Conver 0-based slot to 1-based client index. Look at UTIL_GetCommandClientIndex() usage for reference.
  301. }
  302. #else
  303. return 0;
  304. #endif
  305. }
  306. virtual int IsInEditMode( void )
  307. {
  308. #ifdef DEDICATED
  309. return false;
  310. #else
  311. return g_bInEditMode;
  312. #endif
  313. }
  314. virtual int IsInCommentaryMode( void )
  315. {
  316. #ifdef DEDICATED
  317. return false;
  318. #else
  319. return g_bInCommentaryMode;
  320. #endif
  321. }
  322. virtual KeyValues* GetLaunchOptions( void )
  323. {
  324. return g_pLaunchOptions;
  325. }
  326. virtual bool IsLevelMainMenuBackground( void )
  327. {
  328. return sv.IsLevelMainMenuBackground();
  329. }
  330. virtual void NotifyEdictFlagsChange( int iEdict )
  331. {
  332. if ( g_pLocalNetworkBackdoor )
  333. g_pLocalNetworkBackdoor->NotifyEdictFlagsChange( iEdict );
  334. }
  335. virtual const CCheckTransmitInfo* GetPrevCheckTransmitInfo( edict_t *pPlayerEdict )
  336. {
  337. int entnum = NUM_FOR_EDICT( pPlayerEdict );
  338. if ( entnum < 1 || entnum > sv.GetClientCount() )
  339. {
  340. Error( "Invalid client specified in GetPrevCheckTransmitInfo\n" );
  341. return NULL;
  342. }
  343. CGameClient *client = sv.Client( entnum-1 );
  344. return client->GetPrevPackInfo();
  345. }
  346. virtual int PrecacheDecal( const char *name, bool preload /*=false*/ )
  347. {
  348. PR_CheckEmptyString( name );
  349. int i = SV_FindOrAddDecal( name, preload );
  350. if ( i >= 0 )
  351. {
  352. return i;
  353. }
  354. Host_Error( "CVEngineServer::PrecacheDecal: '%s' overflow, too many decals", name );
  355. return 0;
  356. }
  357. virtual int PrecacheModel( const char *s, bool preload /*= false*/ )
  358. {
  359. PR_CheckEmptyString (s);
  360. int i = SV_FindOrAddModel( s, preload );
  361. if ( i >= 0 )
  362. {
  363. return i;
  364. }
  365. Host_Error( "CVEngineServer::PrecacheModel: '%s' overflow, too many models", s );
  366. return 0;
  367. }
  368. virtual int PrecacheGeneric(const char *s, bool preload /*= false*/ )
  369. {
  370. int i;
  371. PR_CheckEmptyString (s);
  372. i = SV_FindOrAddGeneric( s, preload );
  373. if (i >= 0)
  374. {
  375. return i;
  376. }
  377. Host_Error ("CVEngineServer::PrecacheGeneric: '%s' overflow", s);
  378. return 0;
  379. }
  380. virtual bool IsModelPrecached( char const *s ) const
  381. {
  382. int idx = SV_ModelIndex( s );
  383. return idx != -1 ? true : false;
  384. }
  385. virtual bool IsDecalPrecached( char const *s ) const
  386. {
  387. int idx = SV_DecalIndex( s );
  388. return idx != -1 ? true : false;
  389. }
  390. virtual bool IsGenericPrecached( char const *s ) const
  391. {
  392. int idx = SV_GenericIndex( s );
  393. return idx != -1 ? true : false;
  394. }
  395. virtual void ForceExactFile( const char *s )
  396. {
  397. PR_CheckEmptyString( s );
  398. SV_ForceExactFile( s );
  399. }
  400. virtual void ForceModelBounds( const char *s, const Vector &mins, const Vector &maxs )
  401. {
  402. PR_CheckEmptyString( s );
  403. SV_ForceModelBounds( s, mins, maxs );
  404. }
  405. virtual void ForceSimpleMaterial( const char *s )
  406. {
  407. PR_CheckEmptyString( s );
  408. SV_ForceSimpleMaterial( s );
  409. }
  410. virtual bool IsInternalBuild( void )
  411. {
  412. return !phonehome->IsExternalBuild();
  413. }
  414. //-----------------------------------------------------------------------------
  415. // Purpose: Precache a sentence file (parse on server, send to client)
  416. // Input : *s - file name
  417. //-----------------------------------------------------------------------------
  418. virtual int PrecacheSentenceFile( const char *s, bool preload /*= false*/ )
  419. {
  420. // UNDONE: Set up preload flag
  421. // UNDONE: Send this data to the client to support multiple sentence files
  422. VOX_ReadSentenceFile( s );
  423. return 0;
  424. }
  425. //-----------------------------------------------------------------------------
  426. // Purpose: Retrieves the pvs for an origin into the specified array
  427. // Input : *org - origin
  428. // outputpvslength - size of outputpvs array in bytes
  429. // *outputpvs - If null, then return value is the needed length
  430. // Output : int - length of pvs array used ( in bytes )
  431. //-----------------------------------------------------------------------------
  432. virtual int GetClusterForOrigin( const Vector& org )
  433. {
  434. return CM_LeafCluster( CM_PointLeafnum( org ) );
  435. }
  436. virtual int GetPVSForCluster( int clusterIndex, int outputpvslength, unsigned char *outputpvs )
  437. {
  438. int length = (CM_NumClusters()+7)>>3;
  439. if ( outputpvs )
  440. {
  441. if ( outputpvslength < length )
  442. {
  443. Sys_Error( "GetPVSForOrigin called with inusfficient sized pvs array, need %i bytes!", length );
  444. return length;
  445. }
  446. CM_Vis( outputpvs, outputpvslength, clusterIndex, DVIS_PVS );
  447. }
  448. return length;
  449. }
  450. //-----------------------------------------------------------------------------
  451. // Purpose: Test origin against pvs array retreived from GetPVSForOrigin
  452. // Input : *org - origin to chec
  453. // checkpvslength - length of pvs array
  454. // *checkpvs -
  455. // Output : bool - true if entity is visible
  456. //-----------------------------------------------------------------------------
  457. virtual bool CheckOriginInPVS( const Vector& org, const unsigned char *checkpvs, int checkpvssize )
  458. {
  459. int clusterIndex = CM_LeafCluster( CM_PointLeafnum( org ) );
  460. if ( clusterIndex < 0 )
  461. return false;
  462. int offset = clusterIndex>>3;
  463. if ( offset > checkpvssize )
  464. {
  465. Sys_Error( "CheckOriginInPVS: cluster would read past end of pvs data (%i:%i)\n",
  466. offset, checkpvssize );
  467. return false;
  468. }
  469. if ( !(checkpvs[offset] & (1<<(clusterIndex&7)) ) )
  470. {
  471. return false;
  472. }
  473. return true;
  474. }
  475. //-----------------------------------------------------------------------------
  476. // Purpose: Test origin against pvs array retreived from GetPVSForOrigin
  477. // Input : *org - origin to chec
  478. // checkpvslength - length of pvs array
  479. // *checkpvs -
  480. // Output : bool - true if entity is visible
  481. //-----------------------------------------------------------------------------
  482. virtual bool CheckBoxInPVS( const Vector& mins, const Vector& maxs, const unsigned char *checkpvs, int checkpvssize )
  483. {
  484. if ( !CM_BoxVisible( mins, maxs, checkpvs, checkpvssize ) )
  485. {
  486. return false;
  487. }
  488. return true;
  489. }
  490. virtual int GetPlayerUserId( const edict_t *e )
  491. {
  492. if ( !sv.IsActive() || !e)
  493. return -1;
  494. for ( int i = 0; i < sv.GetClientCount(); i++ )
  495. {
  496. CGameClient *cl = sv.Client(i);
  497. if ( cl->edict == e )
  498. {
  499. return cl->m_UserID;
  500. }
  501. }
  502. // Couldn't find it
  503. return -1;
  504. }
  505. virtual const char *GetPlayerNetworkIDString( const edict_t *e )
  506. {
  507. if ( !sv.IsActive() || !e)
  508. return NULL;
  509. for ( int i = 0; i < sv.GetClientCount(); i++ )
  510. {
  511. CGameClient *cl = sv.Client(i);
  512. if ( cl->edict == e )
  513. {
  514. return cl->GetNetworkIDString();
  515. }
  516. }
  517. // Couldn't find it
  518. return NULL;
  519. }
  520. virtual bool IsUserIDInUse( int userID )
  521. {
  522. if ( !sv.IsActive() )
  523. return false;
  524. for ( int i = 0; i < sv.GetClientCount(); i++ )
  525. {
  526. CGameClient *cl = sv.Client(i);
  527. if ( cl->GetUserID() == userID )
  528. {
  529. return true;
  530. }
  531. }
  532. // Couldn't find it
  533. return false;
  534. }
  535. virtual int GetLoadingProgressForUserID( int userID )
  536. {
  537. if ( !sv.IsActive() )
  538. return false;
  539. for ( int i = 0; i < sv.GetClientCount(); i++ )
  540. {
  541. CGameClient *cl = sv.Client(i);
  542. if ( cl->GetUserID() == userID )
  543. {
  544. return cl->m_nLoadingProgress;
  545. }
  546. }
  547. // Couldn't find it
  548. return -1;
  549. }
  550. virtual int GetEntityCount( void )
  551. {
  552. return sv.num_edicts;
  553. }
  554. virtual INetChannelInfo* GetPlayerNetInfo( int playerIndex )
  555. {
  556. if ( playerIndex < 1 || playerIndex > sv.GetClientCount() )
  557. return NULL;
  558. CGameClient *client = sv.Client( playerIndex - 1 );
  559. return client->m_NetChannel;
  560. }
  561. virtual edict_t* CreateEdict( int iForceEdictIndex )
  562. {
  563. edict_t *pedict = ED_Alloc( iForceEdictIndex );
  564. if ( g_pServerPluginHandler )
  565. {
  566. g_pServerPluginHandler->OnEdictAllocated( pedict );
  567. }
  568. return pedict;
  569. }
  570. virtual void RemoveEdict(edict_t* ed)
  571. {
  572. if ( g_pServerPluginHandler )
  573. {
  574. g_pServerPluginHandler->OnEdictFreed( ed );
  575. }
  576. ED_Free(ed);
  577. }
  578. //
  579. // Request engine to allocate "cb" bytes on the entity's private data pointer.
  580. //
  581. virtual void *PvAllocEntPrivateData( long cb )
  582. {
  583. return calloc( 1, cb );
  584. }
  585. //
  586. // Release the private data memory, if any.
  587. //
  588. virtual void FreeEntPrivateData( void *pEntity )
  589. {
  590. #if defined( _DEBUG ) && defined( WIN32 )
  591. // set the memory to a known value
  592. int size = _msize( pEntity );
  593. memset( pEntity, 0xDD, size );
  594. #endif
  595. if ( pEntity )
  596. {
  597. free( pEntity );
  598. }
  599. }
  600. virtual void *SaveAllocMemory( size_t num, size_t size )
  601. {
  602. #ifndef DEDICATED
  603. return ::SaveAllocMemory(num, size);
  604. #else
  605. return NULL;
  606. #endif
  607. }
  608. virtual void SaveFreeMemory( void *pSaveMem )
  609. {
  610. #ifndef DEDICATED
  611. ::SaveFreeMemory(pSaveMem);
  612. #endif
  613. }
  614. /*
  615. =================
  616. EmitAmbientSound
  617. =================
  618. */
  619. virtual void EmitAmbientSound( int entindex, const Vector& pos, const char *samp, float vol,
  620. soundlevel_t soundlevel, int fFlags, int pitch, float soundtime /*=0.0f*/ )
  621. {
  622. SoundInfo_t sound;
  623. sound.SetDefault();
  624. sound.nEntityIndex = entindex;
  625. sound.fVolume = vol;
  626. sound.Soundlevel = soundlevel;
  627. sound.nFlags = fFlags;
  628. sound.nPitch = pitch;
  629. sound.nChannel = CHAN_STATIC;
  630. sound.vOrigin = pos;
  631. sound.bIsAmbient = true;
  632. ASSERT_COORD( sound.vOrigin );
  633. // set sound delay
  634. if ( soundtime != 0.0f )
  635. {
  636. sound.fDelay = soundtime - sv.GetTime();
  637. sound.nFlags |= SND_DELAY;
  638. }
  639. // if this is a sentence, get sentence number
  640. if ( TestSoundChar(samp, CHAR_SENTENCE) )
  641. {
  642. sound.bIsSentence = true;
  643. sound.nSoundNum = Q_atoi( PSkipSoundChars(samp) );
  644. if ( sound.nSoundNum >= (unsigned int)VOX_SentenceCount() )
  645. {
  646. ConMsg("EmitAmbientSound: invalid sentence number: %s", PSkipSoundChars(samp));
  647. return;
  648. }
  649. }
  650. else
  651. {
  652. // check to see if samp was properly precached
  653. sound.bIsSentence = false;
  654. sound.nSoundNum = SV_SoundIndex( samp );
  655. if (sound.nSoundNum <= 0)
  656. {
  657. ConMsg ("EmitAmbientSound: sound not precached: %s\n", samp);
  658. return;
  659. }
  660. }
  661. if ( (fFlags & SND_SPAWNING) && sv.allowsignonwrites )
  662. {
  663. CSVCMsg_Sounds_t sndmsg;
  664. sndmsg.set_reliable_sound( true );
  665. sound.WriteDelta( NULL, sndmsg, sv.GetFinalTickTime() );
  666. // write into signon buffer
  667. if ( !sndmsg.WriteToBuffer( sv.m_Signon ) )
  668. {
  669. Sys_Error( "EmitAmbientSound: Init message would overflow signon buffer!\n" );
  670. return;
  671. }
  672. }
  673. else
  674. {
  675. if ( fFlags & SND_SPAWNING )
  676. {
  677. DevMsg("EmitAmbientSound: warning, broadcasting sound labled as SND_SPAWNING.\n" );
  678. }
  679. // send sound to all active players
  680. CEngineRecipientFilter filter;
  681. filter.AddAllPlayers();
  682. filter.MakeReliable();
  683. sv.BroadcastSound( sound, filter );
  684. }
  685. }
  686. virtual void FadeClientVolume(const edict_t *clientent,
  687. float fadePercent, float fadeOutSeconds, float holdTime, float fadeInSeconds)
  688. {
  689. int entnum = NUM_FOR_EDICT(clientent);
  690. if (entnum < 1 || entnum > sv.GetClientCount() )
  691. {
  692. ConMsg ("tried to DLL_FadeClientVolume a non-client\n");
  693. return;
  694. }
  695. IClient *client = sv.Client(entnum-1);
  696. CNETMsg_StringCmd_t sndMsg( va("soundfade %.1f %.1f %.1f %.1f", fadePercent, holdTime, fadeOutSeconds, fadeInSeconds ) );
  697. client->SendNetMsg( sndMsg );
  698. }
  699. //-----------------------------------------------------------------------------
  700. //
  701. // Sentence API
  702. //
  703. //-----------------------------------------------------------------------------
  704. virtual int SentenceGroupPick( int groupIndex, char *name, int nameLen )
  705. {
  706. if ( !name )
  707. {
  708. Sys_Error( "SentenceGroupPick with NULL name\n" );
  709. }
  710. Assert( nameLen > 0 );
  711. return VOX_GroupPick( groupIndex, name, nameLen );
  712. }
  713. virtual int SentenceGroupPickSequential( int groupIndex, char *name, int nameLen, int sentenceIndex, int reset )
  714. {
  715. if ( !name )
  716. {
  717. Sys_Error( "SentenceGroupPickSequential with NULL name\n" );
  718. }
  719. Assert( nameLen > 0 );
  720. return VOX_GroupPickSequential( groupIndex, name, nameLen, sentenceIndex, reset );
  721. }
  722. virtual int SentenceIndexFromName( const char *pSentenceName )
  723. {
  724. if ( !pSentenceName )
  725. {
  726. Sys_Error( "SentenceIndexFromName with NULL pSentenceName\n" );
  727. }
  728. int sentenceIndex = -1;
  729. VOX_LookupString( pSentenceName, &sentenceIndex );
  730. return sentenceIndex;
  731. }
  732. virtual const char *SentenceNameFromIndex( int sentenceIndex )
  733. {
  734. return VOX_SentenceNameFromIndex( sentenceIndex );
  735. }
  736. virtual int SentenceGroupIndexFromName( const char *pGroupName )
  737. {
  738. if ( !pGroupName )
  739. {
  740. Sys_Error( "SentenceGroupIndexFromName with NULL pGroupName\n" );
  741. }
  742. return VOX_GroupIndexFromName( pGroupName );
  743. }
  744. virtual const char *SentenceGroupNameFromIndex( int groupIndex )
  745. {
  746. return VOX_GroupNameFromIndex( groupIndex );
  747. }
  748. virtual float SentenceLength( int sentenceIndex )
  749. {
  750. return VOX_SentenceLength( sentenceIndex );
  751. }
  752. //-----------------------------------------------------------------------------
  753. virtual int CheckHeadnodeVisible( int nodenum, const byte *visbits, int vissize )
  754. {
  755. return CM_HeadnodeVisible(nodenum, visbits, vissize );
  756. }
  757. /*
  758. =================
  759. ServerCommand
  760. Sends text to servers execution buffer
  761. localcmd (string)
  762. =================
  763. */
  764. virtual void ServerCommand( const char *str )
  765. {
  766. if ( !str )
  767. {
  768. Sys_Error( "ServerCommand with NULL string\n" );
  769. }
  770. if ( ValidCmd( str ) )
  771. {
  772. Cbuf_AddText( CBUF_SERVER, str );
  773. }
  774. else
  775. {
  776. ConMsg( "Error, bad server command %s\n", str );
  777. }
  778. }
  779. /*
  780. =================
  781. ServerExecute
  782. Executes all commands in server buffer
  783. localcmd (string)
  784. =================
  785. */
  786. virtual void ServerExecute( void )
  787. {
  788. Cbuf_Execute();
  789. }
  790. /*
  791. =================
  792. ClientCommand
  793. Sends text over to the client's execution buffer
  794. stuffcmd (clientent, value)
  795. =================
  796. */
  797. virtual void ClientCommand(edict_t* pEdict, const char* szFmt, ...)
  798. {
  799. va_list argptr;
  800. static char szOut[1024];
  801. va_start(argptr, szFmt);
  802. Q_vsnprintf(szOut, sizeof( szOut ), szFmt, argptr);
  803. va_end(argptr);
  804. if ( szOut[0] == 0 )
  805. {
  806. Warning( "ClientCommand, 0 length string supplied.\n" );
  807. return;
  808. }
  809. int entnum = NUM_FOR_EDICT( pEdict );
  810. if ( ( entnum < 1 ) || ( entnum > sv.GetClientCount() ) )
  811. {
  812. ConMsg("\n!!!\n\nStuffCmd: Some entity tried to stuff '%s' to console buffer of entity %i when maxclients was set to %i, ignoring\n\n",
  813. szOut, entnum, sv.GetMaxClients() );
  814. return;
  815. }
  816. CNETMsg_StringCmd_t string( szOut );
  817. sv.GetClient(entnum-1)->SendNetMsg( string );
  818. }
  819. // Send a client command keyvalues
  820. // keyvalues are deleted inside the function
  821. virtual void ClientCommandKeyValues( edict_t *pEdict, KeyValues *pCommand )
  822. {
  823. if ( !pCommand )
  824. return;
  825. // Ensure the contract of deleting the key values here
  826. KeyValues::AutoDelete autodelete_pCommand( pCommand );
  827. int entnum = NUM_FOR_EDICT( pEdict );
  828. if ( ( entnum < 1 ) || ( entnum > sv.GetClientCount() ) )
  829. {
  830. ConMsg("\n!!!\n\nClientCommandKeyValues: Some entity tried to stuff '%s' to console buffer of entity %i when maxclients was set to %i, ignoring\n\n",
  831. pCommand->GetName(), entnum, sv.GetMaxClients() );
  832. return;
  833. }
  834. CSVCMsg_CmdKeyValues_t cmd;
  835. CmdKeyValuesHelper::SVCMsg_SetKeyValues( cmd, pCommand );
  836. sv.GetClient(entnum-1)->SendNetMsg( cmd );
  837. }
  838. /*
  839. ===============
  840. LightStyle
  841. void(float style, string value) lightstyle
  842. ===============
  843. */
  844. virtual void LightStyle(int style, const char* val)
  845. {
  846. if ( !val )
  847. {
  848. Sys_Error( "LightStyle with NULL value!\n" );
  849. }
  850. // change the string in string table
  851. INetworkStringTable *stringTable = sv.GetLightStyleTable();
  852. stringTable->SetStringUserData( style, Q_strlen(val)+1, val );
  853. }
  854. virtual void StaticDecal( const Vector& origin, int decalIndex, int entityIndex, int modelIndex, bool lowpriority )
  855. {
  856. CSVCMsg_BSPDecal_t decal;
  857. decal.mutable_pos()->set_x( origin.x );
  858. decal.mutable_pos()->set_y( origin.y );
  859. decal.mutable_pos()->set_z( origin.z );
  860. decal.set_decal_texture_index( decalIndex );
  861. decal.set_entity_index( entityIndex );
  862. decal.set_model_index( modelIndex );
  863. decal.set_low_priority( lowpriority );
  864. if ( sv.allowsignonwrites )
  865. {
  866. decal.WriteToBuffer( sv.m_Signon );
  867. }
  868. else
  869. {
  870. sv.BroadcastMessage( decal, false, true );
  871. }
  872. }
  873. void Message_DetermineMulticastRecipients( bool usepas, const Vector& origin, CPlayerBitVec& playerbits )
  874. {
  875. SV_DetermineMulticastRecipients( usepas, origin, playerbits );
  876. }
  877. /*
  878. ===============================================================================
  879. MESSAGE WRITING
  880. ===============================================================================
  881. */
  882. virtual bf_write *EntityMessageBegin( int ent_index, ServerClass * ent_class, bool reliable )
  883. {
  884. if ( s_MsgData.started )
  885. {
  886. Sys_Error( "EntityMessageBegin: New message started before matching call to EndMessage.\n " );
  887. return NULL;
  888. }
  889. s_MsgData.Reset();
  890. Assert( ent_class );
  891. s_MsgData.filter = NULL;
  892. s_MsgData.reliable = reliable;
  893. s_MsgData.started = true;
  894. s_MsgData.entityMsg.set_ent_index( ent_index );
  895. s_MsgData.entityMsg.set_class_id( ent_class->m_ClassID );
  896. s_MsgData.m_DataOut.Reset();
  897. return &s_MsgData.m_DataOut;
  898. }
  899. // Validates user message type and checks to see if it's variable length
  900. // returns true if variable length
  901. int Message_CheckMessageLength()
  902. {
  903. int bytesWritten = s_MsgData.m_DataOut.GetNumBytesWritten();
  904. if ( bytesWritten > MAX_ENTITY_MSG_DATA ) // TODO use a define or so
  905. {
  906. Warning( "Entity Message to %i, %i bytes written (max is %d)\n",
  907. s_MsgData.entityMsg.ent_index(), bytesWritten, MAX_ENTITY_MSG_DATA );
  908. return -1;
  909. }
  910. return bytesWritten; // all checks passed, estimated final length
  911. }
  912. virtual void MessageEnd( void )
  913. {
  914. if ( !s_MsgData.started )
  915. {
  916. Sys_Error( "MESSAGE_END called with no active message\n" );
  917. return;
  918. }
  919. int length = Message_CheckMessageLength();
  920. // check to see if it's a valid message
  921. if ( length < 0 )
  922. {
  923. s_MsgData.Reset(); // clear message data
  924. return;
  925. }
  926. s_MsgData.entityMsg.set_ent_data( s_MsgData.entitydata, s_MsgData.m_DataOut.GetNumBytesWritten() );
  927. if ( s_MsgData.filter )
  928. {
  929. // send entity/user messages only to full connected clients in filter
  930. sv.BroadcastMessage( s_MsgData.entityMsg, *s_MsgData.filter );
  931. }
  932. else
  933. {
  934. // send entity messages to all full connected clients
  935. sv.BroadcastMessage( s_MsgData.entityMsg, true, s_MsgData.reliable );
  936. }
  937. s_MsgData.Reset(); // clear message data
  938. }
  939. virtual void SendUserMessage( IRecipientFilter& filter, int message, const ::google::protobuf::Message &msg )
  940. {
  941. CSVCMsg_UserMessage_t _userMsg;
  942. if ( !msg.IsInitialized() )
  943. {
  944. Msg("SendUserMessage %s(%d) is not initialized! Probably missing required fields!\n", msg.GetTypeName().c_str(), message );
  945. }
  946. int size = msg.ByteSize();
  947. if ( sv_show_usermessage.GetBool() )
  948. {
  949. Msg("SendUserMessage - %s(%d) bytes: %d\n", msg.GetTypeName().c_str(), message, size );
  950. if( sv_show_usermessage.GetInt() > 1 )
  951. Msg("%s", msg.DebugString().c_str() );
  952. }
  953. _userMsg.set_msg_type( message );
  954. _userMsg.mutable_msg_data()->resize( size );
  955. if ( !msg.SerializeWithCachedSizesToArray( (uint8*)&(*_userMsg.mutable_msg_data())[0] ) )
  956. {
  957. Msg( "SendUserMessage: Error serializing %s!\n", msg.GetTypeName().c_str() );
  958. return;
  959. }
  960. sv.BroadcastMessage( _userMsg, filter );
  961. }
  962. /* single print to a specific client */
  963. virtual void ClientPrintf( edict_t *pEdict, const char *szMsg )
  964. {
  965. int entnum = NUM_FOR_EDICT( pEdict );
  966. if (entnum < 1 || entnum > sv.GetClientCount() )
  967. {
  968. ConMsg ("tried to sprint to a non-client\n");
  969. return;
  970. }
  971. sv.Client(entnum-1)->ClientPrintf( "%s", szMsg );
  972. }
  973. #ifdef DEDICATED
  974. void Con_NPrintf( int pos, const char *fmt, ... )
  975. {
  976. }
  977. void Con_NXPrintf( const struct con_nprint_s *info, const char *fmt, ... )
  978. {
  979. }
  980. #else
  981. void Con_NPrintf( int pos, const char *fmt, ... )
  982. {
  983. if ( IsDedicatedServer() )
  984. return;
  985. va_list argptr;
  986. char text[4096];
  987. va_start (argptr, fmt);
  988. Q_vsnprintf(text, sizeof( text ), fmt, argptr);
  989. va_end (argptr);
  990. ::Con_NPrintf( pos, "%s", text );
  991. }
  992. void Con_NXPrintf( const struct con_nprint_s *info, const char *fmt, ... )
  993. {
  994. if ( IsDedicatedServer() )
  995. return;
  996. va_list argptr;
  997. char text[4096];
  998. va_start (argptr, fmt);
  999. Q_vsnprintf(text, sizeof( text ), fmt, argptr);
  1000. va_end (argptr);
  1001. ::Con_NXPrintf( info, "%s", text );
  1002. }
  1003. #endif
  1004. virtual void SetView(const edict_t *clientent, const edict_t *viewent)
  1005. {
  1006. int clientnum = NUM_FOR_EDICT( clientent );
  1007. if (clientnum < 1 || clientnum > sv.GetClientCount() )
  1008. Host_Error ("DLL_SetView: not a client");
  1009. CGameClient *client = sv.Client(clientnum-1);
  1010. client->m_pViewEntity = viewent;
  1011. CSVCMsg_SetView_t view;
  1012. view.set_entity_index( NUM_FOR_EDICT(viewent) );
  1013. client->SendNetMsg( view );
  1014. }
  1015. virtual void CrosshairAngle(const edict_t *clientent, float pitch, float yaw)
  1016. {
  1017. int clientnum = NUM_FOR_EDICT( clientent );
  1018. if (clientnum < 1 || clientnum > sv.GetClientCount() )
  1019. Host_Error ("DLL_Crosshairangle: not a client");
  1020. IClient *client = sv.Client(clientnum-1);
  1021. if (pitch > 180)
  1022. pitch -= 360;
  1023. if (pitch < -180)
  1024. pitch += 360;
  1025. if (yaw > 180)
  1026. yaw -= 360;
  1027. if (yaw < -180)
  1028. yaw += 360;
  1029. CSVCMsg_CrosshairAngle_t crossHairMsg;
  1030. crossHairMsg.mutable_angle()->set_x( pitch );
  1031. crossHairMsg.mutable_angle()->set_y( yaw );
  1032. crossHairMsg.mutable_angle()->set_z( 0 );
  1033. client->SendNetMsg( crossHairMsg );
  1034. }
  1035. virtual void GetGameDir( char *szGetGameDir, int maxlength )
  1036. {
  1037. COM_GetGameDir(szGetGameDir, maxlength );
  1038. }
  1039. virtual int CompareFileTime( const char *filename1, const char *filename2, int *iCompare)
  1040. {
  1041. return COM_CompareFileTime(filename1, filename2, iCompare);
  1042. }
  1043. virtual bool LockNetworkStringTables( bool lock )
  1044. {
  1045. return networkStringTableContainerServer->Lock( lock );
  1046. }
  1047. // For use with FAKE CLIENTS
  1048. virtual edict_t* CreateFakeClient( const char *netname )
  1049. {
  1050. CGameClient *fcl = static_cast<CGameClient*>(sv.CreateFakeClient(netname));
  1051. if ( !fcl )
  1052. {
  1053. // server is full
  1054. return NULL;
  1055. }
  1056. fcl->UpdateUserSettings();
  1057. return fcl->edict;
  1058. }
  1059. // Get a keyvalue for s specified client
  1060. virtual const char *GetClientConVarValue( int clientIndex, const char *name )
  1061. {
  1062. if ( clientIndex < 1 || clientIndex > sv.GetClientCount() )
  1063. {
  1064. DevMsg( 1, "GetClientConVarValue: player invalid index %i\n", clientIndex );
  1065. return "";
  1066. }
  1067. return sv.GetClient( clientIndex - 1 )->GetUserSetting( name );
  1068. }
  1069. virtual const char *ParseFile(const char *data, char *token, int maxlen)
  1070. {
  1071. return ::COM_ParseFile(data, token, maxlen );
  1072. }
  1073. virtual bool CopyFile( const char *source, const char *destination )
  1074. {
  1075. return ::COM_CopyFile( source, destination );
  1076. }
  1077. virtual void AddOriginToPVS( const Vector& origin )
  1078. {
  1079. ::SV_AddOriginToPVS(origin);
  1080. }
  1081. virtual void ResetPVS( byte* pvs, int pvssize )
  1082. {
  1083. ::SV_ResetPVS( pvs, pvssize );
  1084. }
  1085. virtual void SetAreaPortalState( int portalNumber, int isOpen )
  1086. {
  1087. CM_SetAreaPortalState(portalNumber, isOpen);
  1088. }
  1089. virtual void SetAreaPortalStates( const int *portalNumbers, const int *isOpen, int nPortals )
  1090. {
  1091. CM_SetAreaPortalStates( portalNumbers, isOpen, nPortals );
  1092. }
  1093. virtual void DrawMapToScratchPad( IScratchPad3D *pPad, unsigned long iFlags )
  1094. {
  1095. worldbrushdata_t *pData = host_state.worldmodel->brush.pShared;
  1096. if ( !pData )
  1097. return;
  1098. SurfaceHandle_t surfID = SurfaceHandleFromIndex( host_state.worldmodel->brush.firstmodelsurface, pData );
  1099. for (int i=0; i< host_state.worldmodel->brush.nummodelsurfaces; ++i, ++surfID)
  1100. {
  1101. // Don't bother with nodraw surfaces
  1102. if( MSurf_Flags( surfID ) & SURFDRAW_NODRAW )
  1103. continue;
  1104. CSPVertList vertList;
  1105. for ( int iVert=0; iVert < MSurf_VertCount( surfID ); iVert++ )
  1106. {
  1107. int iWorldVert = pData->vertindices[surfID->firstvertindex + iVert];
  1108. const Vector &vPos = pData->vertexes[iWorldVert].position;
  1109. vertList.m_Verts.AddToTail( CSPVert( vPos ) );
  1110. }
  1111. pPad->DrawPolygon( vertList );
  1112. }
  1113. }
  1114. const CBitVec<MAX_EDICTS>* GetEntityTransmitBitsForClient( int iClientIndex )
  1115. {
  1116. if ( iClientIndex < 0 || iClientIndex >= sv.GetClientCount() )
  1117. {
  1118. Assert( false );
  1119. return NULL;
  1120. }
  1121. CGameClient *pClient = sv.Client( iClientIndex );
  1122. CClientFrame *deltaFrame = pClient->GetClientFrame( pClient->m_nDeltaTick );
  1123. if ( !deltaFrame )
  1124. return NULL;
  1125. return &deltaFrame->transmit_entity;
  1126. }
  1127. virtual bool IsPaused()
  1128. {
  1129. return sv.IsPaused();
  1130. }
  1131. virtual float GetTimescale( void ) const
  1132. {
  1133. extern float CL_GetHltvReplayTimeScale();
  1134. return sv.GetTimescale() * host_timescale.GetFloat() * CL_GetHltvReplayTimeScale();
  1135. }
  1136. virtual void SetFakeClientConVarValue( edict_t *pEntity, const char *cvar, const char *value )
  1137. {
  1138. int clientnum = NUM_FOR_EDICT( pEntity );
  1139. if (clientnum < 1 || clientnum > sv.GetClientCount() )
  1140. Host_Error ("DLL_SetView: not a client");
  1141. CGameClient *client = sv.Client(clientnum-1);
  1142. if ( client->IsFakeClient() )
  1143. {
  1144. client->SetUserCVar( cvar, value );
  1145. client->m_bConVarsChanged = true;
  1146. }
  1147. }
  1148. virtual CSharedEdictChangeInfo* GetSharedEdictChangeInfo()
  1149. {
  1150. return &g_SharedEdictChangeInfo;
  1151. }
  1152. virtual IChangeInfoAccessor *GetChangeAccessor( const edict_t *pEdict )
  1153. {
  1154. extern int NUM_FOR_EDICTINFO( const edict_t * e );
  1155. int idx = NUM_FOR_EDICTINFO( pEdict );
  1156. return &sv.edictchangeinfo[ idx ];
  1157. }
  1158. virtual QueryCvarCookie_t StartQueryCvarValue( edict_t *pPlayerEntity, const char *pCvarName )
  1159. {
  1160. int clientnum = NUM_FOR_EDICT( pPlayerEntity );
  1161. if (clientnum < 1 || clientnum > sv.GetClientCount() )
  1162. Host_Error( "StartQueryCvarValue: not a client" );
  1163. CGameClient *client = sv.Client( clientnum-1 );
  1164. return SendCvarValueQueryToClient( client, pCvarName, false );
  1165. }
  1166. // Name of most recently load .sav file
  1167. virtual char const *GetMostRecentlyLoadedFileName()
  1168. {
  1169. #if !defined( DEDICATED )
  1170. return saverestore->GetMostRecentlyLoadedFileName();
  1171. #else
  1172. return "";
  1173. #endif
  1174. }
  1175. virtual char const *GetSaveFileName()
  1176. {
  1177. #if !defined( DEDICATED )
  1178. return saverestore->GetSaveFileName();
  1179. #else
  1180. return "";
  1181. #endif
  1182. }
  1183. // Tells the engine we can immdiately re-use all edict indices
  1184. // even though we may not have waited enough time
  1185. virtual void AllowImmediateEdictReuse( )
  1186. {
  1187. ED_AllowImmediateReuse();
  1188. }
  1189. virtual void SetAchievementMgr( IAchievementMgr *pAchievementMgr )
  1190. {
  1191. g_pAchievementMgr = pAchievementMgr;
  1192. }
  1193. virtual IAchievementMgr *GetAchievementMgr()
  1194. {
  1195. return g_pAchievementMgr;
  1196. }
  1197. virtual int GetAppID()
  1198. {
  1199. return GetSteamAppID();
  1200. }
  1201. virtual bool IsLowViolence();
  1202. virtual bool IsAnyClientLowViolence();
  1203. /*
  1204. =================
  1205. InsertServerCommand
  1206. Sends text to servers execution buffer
  1207. localcmd (string)
  1208. =================
  1209. */
  1210. virtual void InsertServerCommand( const char *str )
  1211. {
  1212. if ( !str )
  1213. {
  1214. Sys_Error( "InsertServerCommand with NULL string\n" );
  1215. }
  1216. if ( ValidCmd( str ) )
  1217. {
  1218. Cbuf_InsertText( CBUF_SERVER, str );
  1219. }
  1220. else
  1221. {
  1222. ConMsg( "Error, bad server command %s (InsertServerCommand)\n", str );
  1223. }
  1224. }
  1225. bool GetPlayerInfo( int ent_num, player_info_t *pinfo )
  1226. {
  1227. // Entity numbers are offset by 1 from the player numbers
  1228. return sv.GetPlayerInfo( (ent_num-1), pinfo );
  1229. }
  1230. bool IsClientFullyAuthenticated( edict_t *pEdict )
  1231. {
  1232. int entnum = NUM_FOR_EDICT( pEdict );
  1233. if (entnum < 1 || entnum > sv.GetClientCount() )
  1234. return false;
  1235. // Entity numbers are offset by 1 from the player numbers
  1236. CGameClient *client = sv.Client(entnum-1);
  1237. if ( client )
  1238. return client->IsFullyAuthenticated();
  1239. return false;
  1240. }
  1241. virtual ISPSharedMemory *GetSinglePlayerSharedMemorySpace( const char *szName, int ent_num = MAX_EDICTS )
  1242. {
  1243. return g_pSinglePlayerSharedMemoryManager->GetSharedMemory( szName, ent_num );
  1244. }
  1245. virtual void *AllocLevelStaticData( size_t bytes )
  1246. {
  1247. return Hunk_AllocName( bytes, "AllocLevelStaticData", false );
  1248. }
  1249. bool IsSplitScreenPlayer( int entnum )
  1250. {
  1251. if (entnum < 1 || entnum > sv.GetClientCount() )
  1252. return false;
  1253. CGameClient *client = sv.Client(entnum-1);
  1254. return client->IsSplitScreenUser();
  1255. }
  1256. edict_t *GetSplitScreenPlayerAttachToEdict( int ent_num )
  1257. {
  1258. if (ent_num < 1 || ent_num > sv.GetClientCount() )
  1259. return NULL;
  1260. CGameClient *client = sv.Client(ent_num-1);
  1261. if ( !client->IsSplitScreenUser() )
  1262. return NULL;
  1263. Assert( client->m_pAttachedTo );
  1264. if ( !client->m_pAttachedTo )
  1265. return NULL;
  1266. return static_cast< CGameClient * >( client->m_pAttachedTo )->edict;
  1267. }
  1268. CrossPlayPlatform_t GetClientCrossPlayPlatform( int entnum )
  1269. {
  1270. if (entnum < 1 || entnum > sv.GetClientCount() )
  1271. return CROSSPLAYPLATFORM_UNKNOWN;
  1272. CGameClient *client = sv.Client(entnum-1);
  1273. return client->GetClientPlatform();
  1274. }
  1275. void EnsureInstanceBaseline( int ent_num )
  1276. {
  1277. edict_t *pEnt = EDICT_NUM( ent_num );
  1278. Assert ( pEnt && pEnt->GetNetworkable() );
  1279. if ( pEnt && pEnt->GetNetworkable() )
  1280. {
  1281. SerializedEntityHandle_t handle = g_pSerializedEntities->AllocateSerializedEntity(__FILE__, __LINE__);
  1282. Assert( handle != SERIALIZED_ENTITY_HANDLE_INVALID);
  1283. if ( handle != SERIALIZED_ENTITY_HANDLE_INVALID )
  1284. {
  1285. ServerClass *pServerClass = pEnt->GetNetworkable()->GetServerClass();
  1286. SV_EnsureInstanceBaseline( pServerClass, ent_num, handle );
  1287. }
  1288. g_pSerializedEntities->ReleaseSerializedEntity( handle );
  1289. }
  1290. }
  1291. // Sets server reservation payload
  1292. bool ReserveServerForQueuedGame( char const *szReservationPayload )
  1293. {
  1294. bool bResult = sv.ReserveServerForQueuedGame( szReservationPayload );
  1295. if ( bResult && szReservationPayload && ( szReservationPayload[0] != 'R' ) )
  1296. {
  1297. ServerCommand( "removeallids\n" );
  1298. }
  1299. return bResult;
  1300. }
  1301. bool GetEngineHltvInfo( CEngineHltvInfo_t &info )
  1302. {
  1303. Q_memset( &info, 0, sizeof( info ) );
  1304. CActiveHltvServerIterator hltv;
  1305. if ( !hltv )
  1306. return false; // broadcast is not active, no active GOTV[] instances
  1307. info.m_bBroadcastActive = true;
  1308. info.m_bMasterProxy = !hltv->IsDemoPlayback() && hltv->IsMasterProxy();
  1309. if ( info.m_bMasterProxy )
  1310. info.m_flDelay = hltv->GetDirector()->GetDelay();
  1311. info.m_nTvPort = hltv->GetUDPPort();
  1312. info.m_flTime = hltv->GetTime();
  1313. hltv->GetGlobalStats( info.m_numProxies, info.m_numSlots, info.m_numClients );
  1314. hltv->GetLocalStats( info.m_numLocalProxies, info.m_numLocalSlots, info.m_numLocalClients );
  1315. hltv->GetRelayStats( info.m_numRelayProxies, info.m_numRelaySlots, info.m_numRelayClients );
  1316. hltv->GetExternalStats( info.m_numExternalTotalViewers, info.m_numExternalLinkedViewers );
  1317. const netadr_t *pRelayAdr = info.m_bMasterProxy ? NULL : hltv->GetRelayAddress();
  1318. if ( pRelayAdr )
  1319. {
  1320. info.m_relayAddress = pRelayAdr->GetIPHostByteOrder();
  1321. info.m_relayPort = pRelayAdr->GetPort();
  1322. }
  1323. else
  1324. {
  1325. info.m_relayAddress = 0;
  1326. info.m_relayPort = 0;
  1327. }
  1328. // while ( hltv.Next() )
  1329. // {
  1330. // // ... reduce the information from multiple broadcasts here?
  1331. // }
  1332. return true;
  1333. }
  1334. // Add HLTV proxy whitelist to bypass password and Steam Auth checks upon connection, as CIDR a.b.c.d/numbits
  1335. void AddHltvRelayProxyWhitelist( uint32 a, uint32 b, uint32 c, uint32 d, uint32 numbits )
  1336. {
  1337. HltvRelayProxyWhitelistMask_t mask;
  1338. Q_memset( &mask, 0, sizeof( mask ) );
  1339. mask.a = a;
  1340. mask.b = b;
  1341. mask.c = c;
  1342. mask.d = d;
  1343. mask.numbits = numbits;
  1344. // Add a mask if it hasn't been added yet
  1345. if ( s_arrHltvRelayProxyWhitelist.Find( mask ) == s_arrHltvRelayProxyWhitelist.InvalidIndex() )
  1346. s_arrHltvRelayProxyWhitelist.AddToTail( mask );
  1347. }
  1348. // On master HLTV this call updates number of external viewers and which portion of those are linked with Steam
  1349. void UpdateHltvExternalViewers( uint32 numTotalViewers, uint32 numLinkedViewers )
  1350. {
  1351. for ( CHltvServerIterator hltv; hltv; hltv.Next() )
  1352. {
  1353. hltv->UpdateHltvExternalViewers( numTotalViewers, numLinkedViewers );
  1354. }
  1355. }
  1356. void SetDedicatedServerBenchmarkMode( bool bBenchmarkMode )
  1357. {
  1358. g_bDedicatedServerBenchmarkMode = bBenchmarkMode;
  1359. if ( bBenchmarkMode )
  1360. {
  1361. extern ConVar sv_stressbots;
  1362. sv_stressbots.SetValue( (int)1 );
  1363. }
  1364. }
  1365. // Returns the SteamID of the game server
  1366. const CSteamID *GetGameServerSteamID()
  1367. {
  1368. if ( !Steam3Server().GetGSSteamID().IsValid() )
  1369. return NULL;
  1370. return &Steam3Server().GetGSSteamID();
  1371. }
  1372. int GetNumSplitScreenUsersAttachedToEdict( int ent_num )
  1373. {
  1374. if (ent_num < 1 || ent_num > sv.GetClientCount() )
  1375. return 0;
  1376. CGameClient *client = sv.Client(ent_num-1);
  1377. if ( client->IsSplitScreenUser() )
  1378. return 0;
  1379. int c = 0;
  1380. for ( int i = 1; i < host_state.max_splitscreen_players; ++i )
  1381. {
  1382. if ( client->m_SplitScreenUsers[ i ] )
  1383. ++c;
  1384. }
  1385. return c;
  1386. }
  1387. edict_t *GetSplitScreenPlayerForEdict( int ent_num, int nSlot )
  1388. {
  1389. if (ent_num < 1 || ent_num > sv.GetClientCount() )
  1390. return NULL;
  1391. CGameClient *client = sv.Client(ent_num-1);
  1392. if ( client->IsSplitScreenUser() )
  1393. return NULL;
  1394. if ( nSlot <= 0 || nSlot >= host_state.max_splitscreen_players )
  1395. return NULL;
  1396. CBaseClient *cl = client->m_SplitScreenUsers[ nSlot ];
  1397. if ( !cl )
  1398. return NULL;
  1399. return (( CGameClient * )cl)->edict;
  1400. }
  1401. virtual int GetClusterCount()
  1402. {
  1403. CCollisionBSPData *pBSPData = GetCollisionBSPData();
  1404. if ( pBSPData && pBSPData->map_vis )
  1405. return pBSPData->map_vis->numclusters;
  1406. return 0;
  1407. }
  1408. virtual int GetAllClusterBounds( bbox_t *pBBoxList, int maxBBox )
  1409. {
  1410. CCollisionBSPData *pBSPData = GetCollisionBSPData();
  1411. if ( pBSPData && pBSPData->map_vis && host_state.worldbrush )
  1412. {
  1413. // clamp to max clusters in the map
  1414. if ( maxBBox > pBSPData->map_vis->numclusters )
  1415. {
  1416. maxBBox = pBSPData->map_vis->numclusters;
  1417. }
  1418. // reset all of the bboxes
  1419. for ( int i = 0; i < maxBBox; i++ )
  1420. {
  1421. ClearBounds( pBBoxList[i].mins, pBBoxList[i].maxs );
  1422. }
  1423. // add each leaf's bounds to the bounds for that cluster
  1424. for ( int i = 0; i < host_state.worldbrush->numleafs; i++ )
  1425. {
  1426. mleaf_t *pLeaf = &host_state.worldbrush->leafs[i];
  1427. // skip solid leaves and leaves with cluster < 0
  1428. if ( !(pLeaf->contents & CONTENTS_SOLID) && pLeaf->cluster >= 0 && pLeaf->cluster < maxBBox )
  1429. {
  1430. Vector mins, maxs;
  1431. mins = pLeaf->m_vecCenter - pLeaf->m_vecHalfDiagonal;
  1432. maxs = pLeaf->m_vecCenter + pLeaf->m_vecHalfDiagonal;
  1433. AddPointToBounds( mins, pBBoxList[pLeaf->cluster].mins, pBBoxList[pLeaf->cluster].maxs );
  1434. AddPointToBounds( maxs, pBBoxList[pLeaf->cluster].mins, pBBoxList[pLeaf->cluster].maxs );
  1435. }
  1436. }
  1437. return pBSPData->map_vis->numclusters;
  1438. }
  1439. return 0;
  1440. }
  1441. virtual bool IsCreatingReslist()
  1442. {
  1443. return MapReslistGenerator().IsEnabled();
  1444. }
  1445. virtual bool IsCreatingXboxReslist()
  1446. {
  1447. return MapReslistGenerator().IsCreatingForXbox();
  1448. }
  1449. virtual bool IsDedicatedServerForXbox()
  1450. {
  1451. return sv.IsDedicatedForXbox();
  1452. }
  1453. virtual bool IsDedicatedServerForPS3( void )
  1454. {
  1455. return sv.IsDedicatedForPS3();
  1456. }
  1457. virtual void Pause( bool bPause, bool bForce )
  1458. {
  1459. ConVarRef sv_pausable( "sv_pausable" );
  1460. int oldValue = sv_pausable.GetInt();
  1461. if ( bForce && !oldValue )
  1462. {
  1463. sv_pausable.SetValue( 1 );
  1464. }
  1465. sv.SetPaused( bPause );
  1466. if ( bForce && !oldValue )
  1467. {
  1468. sv_pausable.SetValue( 0 );
  1469. }
  1470. }
  1471. virtual void SetTimescale( float flTimescale )
  1472. {
  1473. sv.SetTimescale( flTimescale );
  1474. }
  1475. virtual bool HasPaintmap()
  1476. {
  1477. return g_PaintManager.m_bShouldRegister;
  1478. }
  1479. virtual bool SpherePaintSurface( const model_t *pModel, const Vector& vPosition, BYTE colorIndex, float flSphereRadius, float flPaintCoatPercent )
  1480. {
  1481. return ShootPaintSphere( pModel, vPosition, colorIndex, flSphereRadius, flPaintCoatPercent );
  1482. }
  1483. virtual void SphereTracePaintSurface( const model_t *pModel, const Vector& vPosition, const Vector& vContactNormal, float flSphereRadius, CUtlVector<BYTE>& surfColors )
  1484. {
  1485. TracePaintSphere( pModel, vPosition, vContactNormal, flSphereRadius, surfColors );
  1486. }
  1487. virtual void RemoveAllPaint()
  1488. {
  1489. g_PaintManager.RemoveAllPaint();
  1490. }
  1491. virtual void PaintAllSurfaces( BYTE color )
  1492. {
  1493. g_PaintManager.PaintAllSurfaces( color );
  1494. }
  1495. virtual void GetPaintmapDataRLE( CUtlVector<uint32> &data )
  1496. {
  1497. g_PaintManager.GetPaintmapDataRLE( data );
  1498. }
  1499. virtual void LoadPaintmapDataRLE( const CUtlVector<uint32> &data )
  1500. {
  1501. g_PaintManager.LoadPaintmapDataRLE( data );
  1502. }
  1503. virtual void RemovePaint( const model_t* pModel )
  1504. {
  1505. g_PaintManager.RemovePaint( pModel );
  1506. }
  1507. virtual void SendPaintmapDataToClient( edict_t *pPlayerEdict )
  1508. {
  1509. int entnum = NUM_FOR_EDICT( pPlayerEdict );
  1510. if (entnum < 1 || entnum > sv.GetClientCount() )
  1511. return;
  1512. // Entity numbers are offset by 1 from the player numbers
  1513. CGameClient *client = sv.Client(entnum-1);
  1514. if ( !client )
  1515. return;
  1516. CUtlVector< uint32 > data;
  1517. g_PaintManager.GetPaintmapDataRLE( data );
  1518. AssertMsg2( data.Count() < NET_MAX_PAYLOAD, "Sending paint data with size [%d bytes] to client, max payload is [%d bytes]\n", data.Count(), NET_MAX_PAYLOAD );
  1519. if ( data.Count() > 0 )
  1520. {
  1521. //handle endian issue between platforms
  1522. CByteswap swap;
  1523. swap.ActivateByteSwapping( !CByteswap::IsMachineBigEndian() );
  1524. swap.SwapBufferToTargetEndian( data.Base(), data.Base(), data.Count() );
  1525. CSVCMsg_PaintmapData_t svcPaintmap;
  1526. int nBytes = data.Count() * sizeof( data.Base()[0] );
  1527. svcPaintmap.set_paintmap( (void*)data.Base(), nBytes );
  1528. client->SendNetMsg( svcPaintmap, true );
  1529. }
  1530. }
  1531. // Returns the SteamID of the specified player. It'll be NULL if the player hasn't authenticated yet.
  1532. const CSteamID *GetClientSteamID( const edict_t *pPlayerEdict, bool bRequireFullyAuthenticated )
  1533. {
  1534. int entnum = NUM_FOR_EDICT( pPlayerEdict );
  1535. if (entnum < 1 || entnum > sv.GetClientCount() )
  1536. return NULL;
  1537. // Entity numbers are offset by 1 from the player numbers
  1538. CGameClient *client = sv.Client(entnum-1);
  1539. if ( !client )
  1540. return NULL;
  1541. if ( !client->m_SteamID.IsValid() )
  1542. return NULL;
  1543. if ( bRequireFullyAuthenticated && !client->IsFullyAuthenticated() )
  1544. return NULL;
  1545. return &client->m_SteamID;
  1546. }
  1547. // Returns the XUID of the specified player. It'll be NULL if the player hasn't connected yet.
  1548. XUID GetClientXUID( edict_t *pPlayerEdict )
  1549. {
  1550. int entnum = NUM_FOR_EDICT( pPlayerEdict );
  1551. if (entnum < 1 || entnum > sv.GetClientCount() )
  1552. return 0ull;
  1553. // Entity numbers are offset by 1 from the player numbers
  1554. CGameClient *client = sv.Client(entnum-1);
  1555. if ( !client )
  1556. return 0ull;
  1557. return client->GetClientXuid();
  1558. }
  1559. void SetGamestatsData( CGamestatsData *pGamestatsData )
  1560. {
  1561. g_pGamestatsData = pGamestatsData;
  1562. }
  1563. CGamestatsData *GetGamestatsData()
  1564. {
  1565. return g_pGamestatsData;
  1566. }
  1567. void HostValidateSession()
  1568. {
  1569. extern void HostValidateSessionImpl();
  1570. HostValidateSessionImpl();
  1571. }
  1572. void RefreshScreenIfNecessary()
  1573. {
  1574. ::RefreshScreenIfNecessary();
  1575. }
  1576. float GetLatencyForChoreoSounds();
  1577. int GetServerVersion() const
  1578. {
  1579. return ::GetServerVersion();
  1580. }
  1581. bool WasShutDownRequested() const
  1582. {
  1583. extern bool sv_ShutDown_WasRequested();
  1584. return sv_ShutDown_WasRequested();
  1585. }
  1586. private:
  1587. // Purpose: Sends a temp entity to the client ( follows the format of the original MESSAGE_BEGIN stuff from HL1
  1588. virtual void PlaybackTempEntity( IRecipientFilter& filter, float delay, const void *pSender, const SendTable *pST, int classID );
  1589. virtual int CheckAreasConnected( int area1, int area2 );
  1590. virtual int GetArea( const Vector& origin );
  1591. virtual void GetAreaBits( int area, unsigned char *bits, int buflen );
  1592. virtual bool GetAreaPortalPlane( Vector const &vViewOrigin, int portalKey, VPlane *pPlane );
  1593. virtual client_textmessage_t *TextMessageGet( const char *pName );
  1594. virtual void LogPrint(const char * msg);
  1595. virtual bool IsLogEnabled();
  1596. virtual bool LoadGameState( char const *pMapName, bool createPlayers );
  1597. virtual bool IsOverrideLoadGameEntsOn();
  1598. virtual void ForceFlushEntity( int iEntity );
  1599. virtual void LoadAdjacentEnts( const char *pOldLevel, const char *pLandmarkName );
  1600. virtual void ClearSaveDir();
  1601. virtual void ClearSaveDirAfterClientLoad();
  1602. virtual const char* GetMapEntitiesString();
  1603. virtual void BuildEntityClusterList( edict_t *pEdict, PVSInfo_t *pPVSInfo );
  1604. virtual void CleanUpEntityClusterList( PVSInfo_t *pPVSInfo );
  1605. virtual void SolidMoved( edict_t *pSolidEnt, ICollideable *pSolidCollide, const Vector* pPrevAbsOrigin, bool accurateBboxTriggerChecks );
  1606. virtual void TriggerMoved( edict_t *pTriggerEnt, bool accurateBboxTriggerChecks );
  1607. virtual ISpatialPartition *CreateSpatialPartition( const Vector& worldmin, const Vector& worldmax ) { return ::CreateSpatialPartition( worldmin, worldmax ); }
  1608. virtual void DestroySpatialPartition( ISpatialPartition *pPartition ) { ::DestroySpatialPartition( pPartition ); }
  1609. public:
  1610. virtual bool IsActiveApp()
  1611. {
  1612. return game->IsActiveApp();
  1613. }
  1614. virtual void SetNoClipEnabled( bool bEnabled )
  1615. {
  1616. extern bool g_bNoClipEnabled;
  1617. g_bNoClipEnabled = bEnabled;
  1618. }
  1619. virtual bool StartClientHltvReplay( int nClientIndex, const HltvReplayParams_t &params ) OVERRIDE
  1620. {
  1621. if ( IClient *pClient = sv.GetClient( nClientIndex ) )
  1622. {
  1623. return pClient->StartHltvReplay( params );
  1624. }
  1625. return false;
  1626. }
  1627. virtual void StopClientHltvReplay( int nClientIndex ) OVERRIDE
  1628. {
  1629. if ( IClient *pClient = sv.GetClient( nClientIndex ) )
  1630. {
  1631. pClient->StopHltvReplay();
  1632. }
  1633. }
  1634. virtual int GetClientHltvReplayDelay( int nClientIndex ) OVERRIDE
  1635. {
  1636. if ( IClient *pClient = sv.GetClient( nClientIndex ) )
  1637. {
  1638. return pClient->GetHltvReplayDelay();
  1639. }
  1640. return 0;
  1641. }
  1642. virtual bool ClientCanStartHltvReplay( int nClientIndex ) OVERRIDE
  1643. {
  1644. if ( IClient* pClient = sv.GetClient( nClientIndex ) )
  1645. {
  1646. return pClient->CanStartHltvReplay();
  1647. }
  1648. return false;
  1649. }
  1650. virtual bool HasHltvReplay( ) OVERRIDE
  1651. {
  1652. CActiveHltvServerIterator hltv;
  1653. return hltv && hltv->GetOldestTick() > 0;
  1654. }
  1655. virtual void ClientResetReplayRequestTime( int nClientIndex ) OVERRIDE
  1656. {
  1657. if ( IClient* pClient = sv.GetClient( nClientIndex ) )
  1658. {
  1659. return pClient->ResetReplayRequestTime();
  1660. }
  1661. }
  1662. virtual bool AnyClientsInHltvReplayMode() OVERRIDE
  1663. {
  1664. return sv.AnyClientsInHltvReplayMode();
  1665. }
  1666. };
  1667. //-----------------------------------------------------------------------------
  1668. // Expose CVEngineServer to the game DLL.
  1669. //-----------------------------------------------------------------------------
  1670. static CVEngineServer g_VEngineServer;
  1671. EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CVEngineServer, IVEngineServer, INTERFACEVERSION_VENGINESERVER, g_VEngineServer);
  1672. //-----------------------------------------------------------------------------
  1673. // Expose CVEngineServer to the engine.
  1674. //-----------------------------------------------------------------------------
  1675. IVEngineServer *g_pVEngineServer = &g_VEngineServer;
  1676. //-----------------------------------------------------------------------------
  1677. // Used to allocate pvs infos
  1678. //-----------------------------------------------------------------------------
  1679. static CUtlMemoryPool s_PVSInfoAllocator( 128, 128 * 64, CUtlMemoryPool::GROW_SLOW, "pvsinfopool", 128 );
  1680. //-----------------------------------------------------------------------------
  1681. // Purpose: Sends a temp entity to the client, using the reliable data stream
  1682. // Input : delay -
  1683. // *pSender -
  1684. // *pST -
  1685. // classID -
  1686. //-----------------------------------------------------------------------------
  1687. static void WriteReliableEvent( const SendTable *pST, float delay, int classID, SerializedEntityHandle_t handle, IClient *client, bf_write *buf )
  1688. {
  1689. CSVCMsg_TempEntities_t eventMsg;
  1690. eventMsg.set_reliable( true );
  1691. // special case 0 signals single reliable event
  1692. eventMsg.set_num_entries( 0 );
  1693. eventMsg.mutable_entity_data()->resize( CEventInfo::MAX_EVENT_DATA );
  1694. bf_write buffer( &(*eventMsg.mutable_entity_data())[0], eventMsg.entity_data().size() );
  1695. if ( delay == 0.0f )
  1696. {
  1697. buffer.WriteOneBit( 0 ); // no delay
  1698. }
  1699. else
  1700. {
  1701. buffer.WriteOneBit( 1 );
  1702. buffer.WriteUBitLong( delay*100.0f, 16 );
  1703. }
  1704. buffer.WriteOneBit( 1 ); // full update
  1705. buffer.WriteUBitLong( classID, sv.serverclassbits ); // classID
  1706. // write event properties
  1707. SendTable_WritePropList( pST, handle, &buffer, -1, NULL );
  1708. // write message
  1709. if ( client )
  1710. {
  1711. client->SendNetMsg( eventMsg, true );
  1712. }
  1713. if ( buf )
  1714. {
  1715. eventMsg.WriteToBuffer( *buf );
  1716. }
  1717. }
  1718. //-----------------------------------------------------------------------------
  1719. // Purpose: Sends a temp entity to the client ( follows the format of the original MESSAGE_BEGIN stuff from HL1
  1720. // Input : msg_dest -
  1721. // delay -
  1722. // *origin -
  1723. // *recipient -
  1724. // *pSender -
  1725. // *pST -
  1726. // classID -
  1727. //-----------------------------------------------------------------------------
  1728. void CVEngineServer::PlaybackTempEntity( IRecipientFilter& filter, float delay, const void *pSender, const SendTable *pST, int classID )
  1729. {
  1730. VPROF( "PlaybackTempEntity" );
  1731. // don't add more events to a snapshot than a client can receive
  1732. if ( sv.m_TempEntities.Count() >= ((1<<CEventInfo::EVENT_INDEX_BITS)-1) )
  1733. {
  1734. // remove oldest effect
  1735. delete sv.m_TempEntities[0];
  1736. sv.m_TempEntities.Remove( 0 );
  1737. }
  1738. // Make this start at 1
  1739. classID = classID + 1;
  1740. SerializedEntityHandle_t handle = g_pSerializedEntities->AllocateSerializedEntity(__FILE__, __LINE__);
  1741. // write all properties, if init or reliable message delta against zero values
  1742. if( !SendTable_Encode( pST, handle, pSender, classID, NULL ) )
  1743. {
  1744. Host_Error( "PlaybackTempEntity: SendTable_Encode returned false (ent %d), overflow?\n", classID );
  1745. return;
  1746. }
  1747. bool bSendReliable = filter.IsReliable();
  1748. // Reliable events are sent one by one to each recipient
  1749. // Unreliable events are queued below and added to delta update packet if there is space...
  1750. if ( bSendReliable )
  1751. {
  1752. int c = filter.GetRecipientCount();
  1753. for ( int slot = 0; slot < c; slot++ )
  1754. {
  1755. int index = filter.GetRecipientIndex( slot );
  1756. if ( index < 1 || index > sv.GetClientCount() )
  1757. continue;
  1758. CGameClient *cl = sv.Client( index - 1 );
  1759. if ( ( cl->IsFakeClient() && !cl->IsHLTV() ) || !cl->IsActive() )
  1760. continue;
  1761. WriteReliableEvent( pST, delay, classID, handle, cl, NULL );
  1762. }
  1763. g_pSerializedEntities->ReleaseSerializedEntity( handle );
  1764. return;
  1765. }
  1766. // create CEventInfo:
  1767. CEventInfo *newEvent = new CEventInfo;
  1768. //copy client filter
  1769. newEvent->filter.AddPlayersFromFilter( &filter );
  1770. newEvent->classID = classID;
  1771. newEvent->pSendTable= pST;
  1772. newEvent->fire_delay= delay;
  1773. newEvent->m_Packed = handle;
  1774. // add to list
  1775. sv.m_TempEntities[sv.m_TempEntities.AddToTail()] = newEvent;
  1776. }
  1777. int CVEngineServer::CheckAreasConnected( int area1, int area2 )
  1778. {
  1779. return CM_AreasConnected(area1, area2);
  1780. }
  1781. //-----------------------------------------------------------------------------
  1782. // Purpose:
  1783. // Input : *origin -
  1784. // *bits -
  1785. // Output : void
  1786. //-----------------------------------------------------------------------------
  1787. int CVEngineServer::GetArea( const Vector& origin )
  1788. {
  1789. return CM_LeafArea( CM_PointLeafnum( origin ) );
  1790. }
  1791. void CVEngineServer::GetAreaBits( int area, unsigned char *bits, int buflen )
  1792. {
  1793. CM_WriteAreaBits( bits, buflen, area );
  1794. }
  1795. bool CVEngineServer::GetAreaPortalPlane( Vector const &vViewOrigin, int portalKey, VPlane *pPlane )
  1796. {
  1797. return CM_GetAreaPortalPlane( vViewOrigin, portalKey, pPlane );
  1798. }
  1799. client_textmessage_t *CVEngineServer::TextMessageGet( const char *pName )
  1800. {
  1801. return ::TextMessageGet( pName );
  1802. }
  1803. void CVEngineServer::LogPrint(const char * msg)
  1804. {
  1805. g_Log.Print( msg );
  1806. }
  1807. bool CVEngineServer::IsLogEnabled()
  1808. {
  1809. return g_Log.IsActive();
  1810. }
  1811. // HACKHACK: Save/restore wrapper - Move this to a different interface
  1812. bool CVEngineServer::LoadGameState( char const *pMapName, bool createPlayers )
  1813. {
  1814. #ifndef DEDICATED
  1815. return saverestore->LoadGameState( pMapName, createPlayers ) != 0;
  1816. #else
  1817. return 0;
  1818. #endif
  1819. }
  1820. bool CVEngineServer::IsOverrideLoadGameEntsOn()
  1821. {
  1822. #ifndef DEDICATED
  1823. return saverestore->IsOverrideLoadGameEntsOn();
  1824. #else
  1825. return false;
  1826. #endif
  1827. }
  1828. void CVEngineServer::ForceFlushEntity( int iEntity )
  1829. {
  1830. if ( g_pLocalNetworkBackdoor )
  1831. {
  1832. g_pLocalNetworkBackdoor->ForceFlushEntity( iEntity );
  1833. }
  1834. }
  1835. void CVEngineServer::LoadAdjacentEnts( const char *pOldLevel, const char *pLandmarkName )
  1836. {
  1837. #ifndef DEDICATED
  1838. saverestore->LoadAdjacentEnts( pOldLevel, pLandmarkName );
  1839. #endif
  1840. }
  1841. void CVEngineServer::ClearSaveDir()
  1842. {
  1843. #ifndef DEDICATED
  1844. saverestore->ClearSaveDir();
  1845. #endif
  1846. }
  1847. void CVEngineServer::ClearSaveDirAfterClientLoad()
  1848. {
  1849. #ifndef DEDICATED
  1850. saverestore->RequestClearSaveDir();
  1851. #endif
  1852. }
  1853. const char* CVEngineServer::GetMapEntitiesString()
  1854. {
  1855. return CM_EntityString();
  1856. }
  1857. //-----------------------------------------------------------------------------
  1858. // Builds PVS information for an entity
  1859. //-----------------------------------------------------------------------------
  1860. inline bool SortClusterLessFunc( const int &left, const int &right )
  1861. {
  1862. return left < right;
  1863. }
  1864. void CVEngineServer::BuildEntityClusterList( edict_t *pEdict, PVSInfo_t *pPVSInfo )
  1865. {
  1866. int i, j;
  1867. int topnode;
  1868. int leafCount;
  1869. int leafs[MAX_TOTAL_ENT_LEAFS], clusters[MAX_TOTAL_ENT_LEAFS];
  1870. int area;
  1871. CleanUpEntityClusterList( pPVSInfo );
  1872. pPVSInfo->m_pClusters = 0;
  1873. pPVSInfo->m_nClusterCount = 0;
  1874. pPVSInfo->m_nAreaNum = 0;
  1875. pPVSInfo->m_nAreaNum2 = 0;
  1876. if ( !pEdict )
  1877. return;
  1878. ICollideable *pCollideable = pEdict->GetCollideable();
  1879. Assert( pCollideable );
  1880. if ( !pCollideable )
  1881. return;
  1882. topnode = -1;
  1883. //get all leafs, including solids
  1884. Vector vecWorldMins, vecWorldMaxs;
  1885. pCollideable->WorldSpaceSurroundingBounds( &vecWorldMins, &vecWorldMaxs );
  1886. leafCount = CM_BoxLeafnums( vecWorldMins, vecWorldMaxs, leafs, MAX_TOTAL_ENT_LEAFS, &topnode );
  1887. // set areas
  1888. bool bAreaCheck = false;
  1889. for ( i = 0; i < leafCount; i++ )
  1890. {
  1891. clusters[i] = CM_LeafCluster( leafs[i] );
  1892. area = CM_LeafArea( leafs[i] );
  1893. if ( area == 0 )
  1894. continue;
  1895. // doors may legally straggle two areas,
  1896. // but nothing should ever need more than that
  1897. if ( pPVSInfo->m_nAreaNum && pPVSInfo->m_nAreaNum != area )
  1898. {
  1899. if ( !bAreaCheck && pPVSInfo->m_nAreaNum2 && pPVSInfo->m_nAreaNum2 != area )
  1900. {
  1901. // if you are touching more than 2 areas, do a check to get the approximate best area
  1902. bAreaCheck = true;
  1903. if ( sv.IsLoading() )
  1904. {
  1905. ConDMsg ("Object touching 3 areas at %f %f %f\n", vecWorldMins[0], vecWorldMins[1], vecWorldMins[2]);
  1906. }
  1907. }
  1908. pPVSInfo->m_nAreaNum2 = area;
  1909. }
  1910. else
  1911. {
  1912. pPVSInfo->m_nAreaNum = area;
  1913. }
  1914. }
  1915. Vector center = (vecWorldMins+vecWorldMaxs) * 0.5f; // calc center
  1916. if ( bAreaCheck )
  1917. {
  1918. // make sure the area of your center is being tested, otherwise just pick the first ones
  1919. // in the list
  1920. int leaf = CM_PointLeafnum( center );
  1921. int area = CM_LeafArea(leaf);
  1922. if ( pPVSInfo->m_nAreaNum != area && pPVSInfo->m_nAreaNum2 != area )
  1923. {
  1924. pPVSInfo->m_nAreaNum = area;
  1925. }
  1926. }
  1927. pPVSInfo->m_nHeadNode = topnode; // save headnode
  1928. // save origin
  1929. pPVSInfo->m_vCenter[0] = center[0];
  1930. pPVSInfo->m_vCenter[1] = center[1];
  1931. pPVSInfo->m_vCenter[2] = center[2];
  1932. if ( leafCount >= MAX_TOTAL_ENT_LEAFS )
  1933. {
  1934. // assume we missed some leafs, and mark by headnode
  1935. pPVSInfo->m_nClusterCount = -1;
  1936. return;
  1937. }
  1938. pPVSInfo->m_pClusters = pPVSInfo->m_pClustersInline;
  1939. if ( leafCount >= 16 )
  1940. {
  1941. std::make_heap( clusters, clusters + leafCount, SortClusterLessFunc );
  1942. std::sort_heap( clusters, clusters + leafCount, SortClusterLessFunc );
  1943. for ( i = 0; i < leafCount; i++ )
  1944. {
  1945. if ( clusters[i] == -1 )
  1946. continue; // not a visible leaf
  1947. if ( ( i > 0 ) && ( clusters[i] == clusters[i-1] ) )
  1948. continue;
  1949. if ( pPVSInfo->m_nClusterCount == MAX_FAST_ENT_CLUSTERS )
  1950. {
  1951. unsigned short *pClusters = (unsigned short *)s_PVSInfoAllocator.Alloc();
  1952. memcpy( pClusters, pPVSInfo->m_pClusters, MAX_FAST_ENT_CLUSTERS * sizeof(unsigned short) );
  1953. pPVSInfo->m_pClusters = pClusters;
  1954. }
  1955. else if ( pPVSInfo->m_nClusterCount == MAX_ENT_CLUSTERS )
  1956. {
  1957. // assume we missed some leafs, and mark by headnode
  1958. s_PVSInfoAllocator.Free( pPVSInfo->m_pClusters );
  1959. pPVSInfo->m_pClusters = 0;
  1960. pPVSInfo->m_nClusterCount = -1;
  1961. break;
  1962. }
  1963. pPVSInfo->m_pClusters[pPVSInfo->m_nClusterCount++] = (short)clusters[i];
  1964. }
  1965. return;
  1966. }
  1967. for ( i = 0; i < leafCount; i++ )
  1968. {
  1969. if ( clusters[i] == -1 )
  1970. continue; // not a visible leaf
  1971. for ( j = 0; j < i; j++ )
  1972. {
  1973. if ( clusters[j] == clusters[i] )
  1974. break;
  1975. }
  1976. if ( j != i )
  1977. continue;
  1978. if ( pPVSInfo->m_nClusterCount == MAX_FAST_ENT_CLUSTERS )
  1979. {
  1980. unsigned short *pClusters = (unsigned short*)s_PVSInfoAllocator.Alloc();
  1981. memcpy( pClusters, pPVSInfo->m_pClusters, MAX_FAST_ENT_CLUSTERS * sizeof(unsigned short) );
  1982. pPVSInfo->m_pClusters = pClusters;
  1983. }
  1984. else if ( pPVSInfo->m_nClusterCount == MAX_ENT_CLUSTERS )
  1985. {
  1986. // assume we missed some leafs, and mark by headnode
  1987. s_PVSInfoAllocator.Free( pPVSInfo->m_pClusters );
  1988. pPVSInfo->m_pClusters = 0;
  1989. pPVSInfo->m_nClusterCount = -1;
  1990. break;
  1991. }
  1992. pPVSInfo->m_pClusters[pPVSInfo->m_nClusterCount++] = (short)clusters[i];
  1993. }
  1994. }
  1995. //-----------------------------------------------------------------------------
  1996. // Cleans up the cluster list
  1997. //-----------------------------------------------------------------------------
  1998. void CVEngineServer::CleanUpEntityClusterList( PVSInfo_t *pPVSInfo )
  1999. {
  2000. if ( pPVSInfo->m_nClusterCount > MAX_FAST_ENT_CLUSTERS )
  2001. {
  2002. s_PVSInfoAllocator.Free( pPVSInfo->m_pClusters );
  2003. pPVSInfo->m_pClusters = 0;
  2004. pPVSInfo->m_nClusterCount = 0;
  2005. }
  2006. }
  2007. //-----------------------------------------------------------------------------
  2008. // Adds a handle to the list of entities to update when a partition query occurs
  2009. //-----------------------------------------------------------------------------
  2010. void CVEngineServer::SolidMoved( edict_t *pSolidEnt, ICollideable *pSolidCollide, const Vector* pPrevAbsOrigin, bool accurateBboxTriggerChecks )
  2011. {
  2012. SV_SolidMoved( pSolidEnt, pSolidCollide, pPrevAbsOrigin, accurateBboxTriggerChecks );
  2013. }
  2014. void CVEngineServer::TriggerMoved( edict_t *pTriggerEnt, bool accurateBboxTriggerChecks )
  2015. {
  2016. SV_TriggerMoved( pTriggerEnt, accurateBboxTriggerChecks );
  2017. }
  2018. //-----------------------------------------------------------------------------
  2019. // Called by the server to determine violence settings.
  2020. //-----------------------------------------------------------------------------
  2021. bool CVEngineServer::IsLowViolence()
  2022. {
  2023. return g_bLowViolence;
  2024. }
  2025. //-----------------------------------------------------------------------------
  2026. // Called by the (multiplayer) server to determine violence settings.
  2027. //-----------------------------------------------------------------------------
  2028. bool CVEngineServer::IsAnyClientLowViolence()
  2029. {
  2030. for ( int i=0; i<sv.GetClientCount(); ++i )
  2031. {
  2032. CGameClient *client = sv.Client(i);
  2033. if ( client && client->IsLowViolenceClient() )
  2034. {
  2035. return true;
  2036. }
  2037. }
  2038. return false;
  2039. }
  2040. //-----------------------------------------------------------------------------
  2041. // Called by server to delay choreo sounds accordingly to IO latency.
  2042. //-----------------------------------------------------------------------------
  2043. float CVEngineServer::GetLatencyForChoreoSounds()
  2044. {
  2045. #ifdef DEDICATED
  2046. return 0.0f;
  2047. #elif LINUX
  2048. return 0.0f;
  2049. #else
  2050. extern ConVar snd_mixahead;
  2051. extern ConVar snd_delay_for_choreo_enabled;
  2052. extern ConVar snd_delay_for_choreo_reset_after_N_milliseconds;
  2053. extern float g_fDelayForChoreo;
  2054. extern uint32 g_nDelayForChoreoLastCheckInMs;
  2055. extern int g_nDelayForChoreoNumberOfSoundsPlaying;
  2056. float fResult = snd_mixahead.GetFloat();
  2057. if ( snd_delay_for_choreo_enabled.GetBool() )
  2058. {
  2059. float fDelayForChoreo = g_fDelayForChoreo;
  2060. if ( fDelayForChoreo != 0.0f )
  2061. {
  2062. // Let's see if we have to reset the delay due to choreo (do this just before we return any useful information from scene entity).
  2063. // Note that this access is not thread safe, however there is no dire consequence here in case of race conditions.
  2064. // Delay may be reset when it should not, or delay may not be reset when it should (that case would be corrected by a subsequent call anyway).
  2065. if ( g_nDelayForChoreoNumberOfSoundsPlaying == 0 )
  2066. {
  2067. // We only reset the delay if no other sound is still behind in term of latency. Several VCDs could be running in parallel.
  2068. // As if we do it later, like when the samples are ready, we are going to hit the timeout more easily. We would then lose previously accumulated delay,
  2069. // and the sound could be potentially cut off later.
  2070. uint32 nCurrentTime = Plat_MSTime();
  2071. uint32 nLastCheck = g_nDelayForChoreoLastCheckInMs;
  2072. if ( nLastCheck + snd_delay_for_choreo_reset_after_N_milliseconds.GetInt() < nCurrentTime )
  2073. {
  2074. // Msg( "Reset delay for choreo as no choreo has been executed for the past %f seconds. Old value=%f.\n", (float)( nCurrentTime - nLastCheck ) / 1000.0f, fDelayForChoreo );
  2075. g_fDelayForChoreo = fDelayForChoreo = 0.0f;
  2076. }
  2077. }
  2078. }
  2079. // Remove the delay to the mix-ahead, which is going to push back the latency.
  2080. fResult -= fDelayForChoreo;
  2081. }
  2082. return fResult;
  2083. #endif
  2084. }