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.

288 lines
7.2 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "voice_gamemgr.h"
  9. #include <string.h>
  10. #include <stdarg.h>
  11. #include <assert.h>
  12. #include "player.h"
  13. #include "ivoiceserver.h"
  14. #include "usermessages.h"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. #define UPDATE_INTERVAL 0.3
  18. // These are stored off as CVoiceGameMgr is created and deleted.
  19. CPlayerBitVec g_PlayerModEnable; // Set to 1 for each player if the player wants to use voice in this mod.
  20. // (If it's zero, then the server reports that the game rules are saying the
  21. // player can't hear anyone).
  22. CPlayerBitVec g_BanMasks[VOICE_MAX_PLAYERS]; // Tells which players don't want to hear each other.
  23. // These are indexed as clients and each bit represents a client
  24. // (so player entity is bit+1).
  25. CPlayerBitVec g_SentGameRulesMasks[VOICE_MAX_PLAYERS]; // These store the masks we last sent to each client so we can determine if
  26. CPlayerBitVec g_SentBanMasks[VOICE_MAX_PLAYERS]; // we need to resend them.
  27. CPlayerBitVec g_bWantModEnable;
  28. ConVar voice_serverdebug( "voice_serverdebug", "0" );
  29. CVoiceGameMgr g_VoiceGameMgr;
  30. // ------------------------------------------------------------------------ //
  31. // Static helpers.
  32. // ------------------------------------------------------------------------ //
  33. // Find a player with a case-insensitive name search.
  34. static CBasePlayer* FindPlayerByName(const char *pTestName)
  35. {
  36. for(int i=1; i <= gpGlobals->maxClients; i++)
  37. {
  38. edict_t *pEdict = INDEXENT(i);
  39. if(pEdict)
  40. {
  41. CBaseEntity *pEnt = CBaseEntity::Instance(pEdict);
  42. if(pEnt && pEnt->IsPlayer())
  43. {
  44. const char *pNetName = STRING(pEnt->GetEntityName());
  45. if(stricmp(pNetName, pTestName) == 0)
  46. {
  47. return (CBasePlayer*)pEnt;
  48. }
  49. }
  50. }
  51. }
  52. return NULL;
  53. }
  54. static void VoiceServerDebug( const char *pFmt, ... )
  55. {
  56. char msg[4096];
  57. va_list marker;
  58. if( !voice_serverdebug.GetInt() )
  59. return;
  60. va_start( marker, pFmt );
  61. _vsnprintf( msg, sizeof(msg), pFmt, marker );
  62. va_end( marker );
  63. Msg( "%s", msg );
  64. }
  65. CVoiceGameMgr* GetVoiceGameMgr()
  66. {
  67. return &g_VoiceGameMgr;
  68. }
  69. // ------------------------------------------------------------------------ //
  70. // CVoiceGameMgr.
  71. // ------------------------------------------------------------------------ //
  72. CVoiceGameMgr::CVoiceGameMgr()
  73. {
  74. m_UpdateInterval = 0;
  75. m_nMaxPlayers = 0;
  76. m_iProximityDistance = -1;
  77. }
  78. CVoiceGameMgr::~CVoiceGameMgr()
  79. {
  80. }
  81. bool CVoiceGameMgr::Init(
  82. IVoiceGameMgrHelper *pHelper,
  83. int maxClients)
  84. {
  85. m_pHelper = pHelper;
  86. m_nMaxPlayers = VOICE_MAX_PLAYERS < maxClients ? VOICE_MAX_PLAYERS : maxClients;
  87. return true;
  88. }
  89. void CVoiceGameMgr::SetHelper(IVoiceGameMgrHelper *pHelper)
  90. {
  91. m_pHelper = pHelper;
  92. }
  93. void CVoiceGameMgr::Update(double frametime)
  94. {
  95. // Only update periodically.
  96. m_UpdateInterval += frametime;
  97. if(m_UpdateInterval < UPDATE_INTERVAL)
  98. return;
  99. UpdateMasks();
  100. }
  101. void CVoiceGameMgr::ClientConnected(struct edict_t *pEdict)
  102. {
  103. int index = ENTINDEX(pEdict) - 1;
  104. // Clear out everything we use for deltas on this guy.
  105. g_bWantModEnable[index] = true;
  106. g_SentGameRulesMasks[index].Init(0);
  107. g_SentBanMasks[index].Init(0);
  108. }
  109. bool CVoiceGameMgr::ClientCommand( CBasePlayer *pPlayer, const CCommand &args )
  110. {
  111. int playerClientIndex = pPlayer->entindex() - 1;
  112. if(playerClientIndex < 0 || playerClientIndex >= m_nMaxPlayers)
  113. {
  114. VoiceServerDebug( "CVoiceGameMgr::ClientCommand: cmd %s from invalid client (%d)\n", args[0], playerClientIndex );
  115. return true;
  116. }
  117. bool bBan = stricmp( args[0], "vban" ) == 0;
  118. if( bBan && args.ArgC() >= 2 )
  119. {
  120. for(int i=1; i < args.ArgC(); i++)
  121. {
  122. unsigned int mask = 0;
  123. sscanf( args[i], "%x", &mask);
  124. if( i <= VOICE_MAX_PLAYERS_DW )
  125. {
  126. VoiceServerDebug( "CVoiceGameMgr::ClientCommand: vban (0x%x) from %d\n", mask, playerClientIndex );
  127. g_BanMasks[playerClientIndex].SetDWord(i-1, mask);
  128. }
  129. else
  130. {
  131. VoiceServerDebug( "CVoiceGameMgr::ClientCommand: invalid index (%d)\n", i );
  132. }
  133. }
  134. // Force it to update the masks now.
  135. //UpdateMasks();
  136. return true;
  137. }
  138. else if(stricmp( args[0], "VModEnable") == 0 && args.ArgC() >= 2)
  139. {
  140. VoiceServerDebug( "CVoiceGameMgr::ClientCommand: VModEnable (%d)\n", !!atoi( args[1] ) );
  141. g_PlayerModEnable[playerClientIndex] = !!atoi( args[1] );
  142. g_bWantModEnable[playerClientIndex] = false;
  143. //UpdateMasks();
  144. return true;
  145. }
  146. else
  147. {
  148. return false;
  149. }
  150. }
  151. void CVoiceGameMgr::UpdateMasks()
  152. {
  153. m_UpdateInterval = 0;
  154. // Note: We now check sv_alltalk in the CanPlayerHearPlayer function, so that function is the authority on whether we can hear another player
  155. for(int iClient=0; iClient < m_nMaxPlayers; iClient++)
  156. {
  157. CBaseEntity *pEnt = UTIL_PlayerByIndex(iClient+1);
  158. if(!pEnt || !pEnt->IsPlayer())
  159. continue;
  160. CBasePlayer *pPlayer = (CBasePlayer*)pEnt;
  161. CSingleUserRecipientFilter user( pPlayer );
  162. // Request the state of their "VModEnable" cvar.
  163. if(g_bWantModEnable[iClient])
  164. {
  165. CCSUsrMsg_RequestState msg;
  166. SendUserMessage( user, CS_UM_RequestState, msg );
  167. // Since this is reliable, only send it once
  168. g_bWantModEnable[iClient] = false;
  169. }
  170. CPlayerBitVec gameRulesMask;
  171. CPlayerBitVec ProximityMask;
  172. bool bProximity = false;
  173. if( g_PlayerModEnable[iClient] )
  174. {
  175. // Build a mask of who they can hear based on the game rules.
  176. for(int iOtherClient=0; iOtherClient < m_nMaxPlayers; iOtherClient++)
  177. {
  178. CBaseEntity *pEnt = UTIL_PlayerByIndex(iOtherClient+1);
  179. if ( pEnt && pEnt->IsPlayer() &&
  180. m_pHelper->CanPlayerHearPlayer( pPlayer, assert_cast<CBasePlayer*>( pEnt ), bProximity ) )
  181. {
  182. gameRulesMask[iOtherClient] = true;
  183. ProximityMask[iOtherClient] = bProximity;
  184. }
  185. }
  186. }
  187. // If this is different from what the client has, send an update.
  188. if(gameRulesMask != g_SentGameRulesMasks[iClient] ||
  189. g_BanMasks[iClient] != g_SentBanMasks[iClient])
  190. {
  191. g_SentGameRulesMasks[iClient] = gameRulesMask;
  192. g_SentBanMasks[iClient] = g_BanMasks[iClient];
  193. CCSUsrMsg_VoiceMask msg;
  194. int dw;
  195. for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++)
  196. {
  197. CCSUsrMsg_VoiceMask::PlayerMask *playerMask = msg.add_player_masks();
  198. playerMask->set_game_rules_mask( gameRulesMask.GetDWord(dw) );
  199. playerMask->set_ban_masks( g_BanMasks[iClient].GetDWord(dw) );
  200. }
  201. msg.set_player_mod_enable( !!g_PlayerModEnable[iClient] );
  202. SendUserMessage( user, CS_UM_VoiceMask, msg );
  203. }
  204. // Tell the engine.
  205. for(int iOtherClient=0; iOtherClient < m_nMaxPlayers; iOtherClient++)
  206. {
  207. bool bCanHear = gameRulesMask[iOtherClient] && !g_BanMasks[iClient][iOtherClient];
  208. g_pVoiceServer->SetClientListening( iClient+1, iOtherClient+1, bCanHear );
  209. if ( bCanHear )
  210. {
  211. g_pVoiceServer->SetClientProximity( iClient+1, iOtherClient+1, !!ProximityMask[iOtherClient] );
  212. }
  213. }
  214. }
  215. }
  216. bool CVoiceGameMgr::IsPlayerIgnoringPlayer( int iTalker, int iListener )
  217. {
  218. return !!g_BanMasks[iListener-1][iTalker-1];
  219. }
  220. void CVoiceGameMgr::SetProximityDistance( int iDistance )
  221. {
  222. m_iProximityDistance = iDistance;
  223. }
  224. bool CVoiceGameMgr::CheckProximity( int iDistance )
  225. {
  226. if ( m_iProximityDistance >= iDistance )
  227. return true;
  228. return false;
  229. }