extensions/sdktools/voice.cpp
changeset 2796 cd0bf02b99cf
parent 2711 858723415154
child 2797 1b63e6a22664
     1.1 --- a/extensions/sdktools/voice.cpp	Mon Sep 07 16:21:48 2009 -0700
     1.2 +++ b/extensions/sdktools/voice.cpp	Mon Sep 07 17:09:28 2009 -0700
     1.3 @@ -42,12 +42,29 @@
     1.4  #define LISTEN_NO			1
     1.5  #define LISTEN_YES			2
     1.6  
     1.7 +/* this enum needs to be in the order as the LISTEN_ defines above to keep
     1.8 +   the old broken SetClientListening functionality untouched */
     1.9 +enum ListenOverride
    1.10 +{
    1.11 +	Listen_Default,		/**< Leave it up to the game */
    1.12 +	Listen_No,			/**< Can't hear */
    1.13 +	Listen_Yes,			/**< Can hear */
    1.14 +};
    1.15 +
    1.16  size_t g_VoiceFlags[65];
    1.17  size_t g_VoiceHookCount = 0;
    1.18 -int g_VoiceMap[65][65];
    1.19 +int g_ClientOverrides[65];
    1.20 +ListenOverride g_VoiceMap[65][65];
    1.21 +bool g_ClientMutes[65][65];
    1.22  
    1.23  SH_DECL_HOOK3(IVoiceServer, SetClientListening, SH_NOATTRIB, 0, bool, int, int, bool);
    1.24  
    1.25 +#if SOURCE_ENGINE >= SE_ORANGEBOX
    1.26 +SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *, const CCommand &);
    1.27 +#else
    1.28 +SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *);
    1.29 +#endif
    1.30 +
    1.31  bool DecHookCount(int amount = 1);
    1.32  bool DecHookCount(int amount)
    1.33  {
    1.34 @@ -72,15 +89,52 @@
    1.35  void SDKTools::VoiceInit()
    1.36  {
    1.37  	memset(g_VoiceMap, 0, sizeof(g_VoiceMap));
    1.38 +	memset(g_ClientOverrides, 0, sizeof(g_ClientOverrides));
    1.39 +	memset(g_ClientMutes, 0, sizeof(g_ClientMutes));
    1.40 +
    1.41 +	SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientCommand, serverClients, this, &SDKTools::OnClientCommand, true);
    1.42  }
    1.43  
    1.44 +#if SOURCE_ENGINE >= SE_ORANGEBOX
    1.45 +void SDKTools::OnClientCommand(edict_t *pEntity, const CCommand &args)
    1.46 +{
    1.47 +#else
    1.48 +void SDKTools::OnClientCommand(edict_t *pEntity)
    1.49 +{
    1.50 +	CCommand args;
    1.51 +#endif
    1.52 +	int client = IndexOfEdict(pEntity);
    1.53 +
    1.54 +	if ((args.ArgC() > 1) && (stricmp(args.Arg(0), "vban") == 0))
    1.55 +	{
    1.56 +		for (int i = 1; (i < args.ArgC()) && (i < 3); i++)
    1.57 +		{
    1.58 +			unsigned long mask = 0;
    1.59 +			sscanf(args[i], "%p", (void**)&mask);
    1.60 +			
    1.61 +			for (int j = 0; j < 32; j++)
    1.62 +			{
    1.63 +				g_ClientMutes[client][1 + j + 32 * (i - 1)] = !!(mask & 1 << j);
    1.64 +			}
    1.65 +		}
    1.66 +	}
    1.67 +
    1.68 +	RETURN_META(MRES_IGNORED);
    1.69 +}
    1.70 +
    1.71 +
    1.72  bool SDKTools::OnSetClientListening(int iReceiver, int iSender, bool bListen)
    1.73  {
    1.74 -	if (g_VoiceMap[iReceiver][iSender] == LISTEN_NO)
    1.75 +	if (g_ClientMutes[iReceiver][iSender])
    1.76  	{
    1.77  		RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, false));
    1.78  	}
    1.79 -	else if (g_VoiceMap[iReceiver][iSender] == LISTEN_YES)
    1.80 +
    1.81 +	if (g_VoiceMap[iReceiver][iSender] == Listen_No)
    1.82 +	{
    1.83 +		RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, false));
    1.84 +	}
    1.85 +	else if (g_VoiceMap[iReceiver][iSender] == Listen_Yes)
    1.86  	{
    1.87  		RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, true));
    1.88  	}
    1.89 @@ -130,7 +184,7 @@
    1.90  	 * of an actual bottleneck.
    1.91  	 */
    1.92  
    1.93 -	/* Reset clients who receive from us */
    1.94 +	/* Reset other clients who receive from or have muted this client */
    1.95  	for (int i = 1; i <= max_clients; i++)
    1.96  	{
    1.97  		if (i == client)
    1.98 @@ -138,9 +192,11 @@
    1.99  			continue;
   1.100  		}
   1.101  
   1.102 -		if (g_VoiceMap[i][client] != LISTEN_DEFAULT)
   1.103 +		g_ClientMutes[i][client] = false;
   1.104 +		
   1.105 +		if (g_VoiceMap[i][client] != Listen_Default)
   1.106  		{
   1.107 -			g_VoiceMap[i][client] = LISTEN_DEFAULT;
   1.108 +			g_VoiceMap[i][client] = Listen_Default;
   1.109  			if (DecHookCount())
   1.110  			{
   1.111  				return;
   1.112 @@ -148,11 +204,16 @@
   1.113  		}
   1.114  	}
   1.115  
   1.116 -	/* Reset clients who send to us.  I'm shoving a count in the 0 index! */
   1.117 -	if (g_VoiceMap[client][0] > 0)
   1.118 +	/* Reset this client's mutes, just in case */
   1.119 +	memset(&g_ClientMutes[client], 0, sizeof(int) * 65);
   1.120 +
   1.121 +	/* Reset other clients who send to this client */
   1.122 +	if (g_ClientOverrides[client] > 0)
   1.123  	{
   1.124 -		DecHookCount(g_VoiceMap[client][0]);
   1.125 -		memset(&g_VoiceMap[client], 0, sizeof(int) * 65);
   1.126 +		DecHookCount(g_ClientOverrides[client]);
   1.127 +		g_ClientOverrides[client] = 0;
   1.128 +		memset(&g_VoiceMap[client], false, sizeof(ListenOverride) * 65);
   1.129 +		memset(&g_ClientMutes[client], false, sizeof(bool) * 65);
   1.130  	}
   1.131  
   1.132  	if (g_VoiceFlags[client])
   1.133 @@ -211,41 +272,41 @@
   1.134  	player = playerhelpers->GetGamePlayer(params[1]);
   1.135  	if (player == NULL)
   1.136  	{
   1.137 -		return pContext->ThrowNativeError("(Receiver) client index %d is invalid", params[1]);
   1.138 +		return pContext->ThrowNativeError("Receiver client index %d is invalid", params[1]);
   1.139  	}
   1.140  	else if (!player->IsConnected())
   1.141  	{
   1.142 -		return pContext->ThrowNativeError("(Receiver) client %d is not connected", params[1]);
   1.143 +		return pContext->ThrowNativeError("Receiver client %d is not connected", params[1]);
   1.144  	}
   1.145  
   1.146  	player = playerhelpers->GetGamePlayer(params[2]);
   1.147  	if (player == NULL)
   1.148  	{
   1.149 -		return pContext->ThrowNativeError("(Sender) client index %d is invalid", params[2]);
   1.150 +		return pContext->ThrowNativeError("Sender client index %d is invalid", params[2]);
   1.151  	}
   1.152  	else if (!player->IsConnected())
   1.153  	{
   1.154 -		return pContext->ThrowNativeError("(Sender) client %d is not connected", params[2]);
   1.155 +		return pContext->ThrowNativeError("Sender client %d is not connected", params[2]);
   1.156  	}
   1.157  
   1.158  	r = params[1];
   1.159  	s = params[2];
   1.160  	
   1.161 -	if (g_VoiceMap[r][s] == LISTEN_DEFAULT && params[3] != LISTEN_DEFAULT)
   1.162 +	if (g_VoiceMap[r][s] == Listen_Default && params[3] != Listen_Default)
   1.163  	{
   1.164 -		g_VoiceMap[r][s] = params[3];
   1.165 -		g_VoiceMap[r][0]++;
   1.166 +		g_VoiceMap[r][s] = (ListenOverride) params[3];
   1.167 +		g_ClientOverrides[r]++;
   1.168  		IncHookCount();
   1.169  	}
   1.170 -	else if (g_VoiceMap[r][s] != LISTEN_DEFAULT && params[3] == LISTEN_DEFAULT)
   1.171 +	else if (g_VoiceMap[r][s] != Listen_Default && params[3] == Listen_Default)
   1.172  	{
   1.173 -		g_VoiceMap[r][s] = params[3];
   1.174 -		g_VoiceMap[r][0]--;
   1.175 +		g_VoiceMap[r][s] = (ListenOverride) params[3];
   1.176 +		g_ClientOverrides[r]--;
   1.177  		DecHookCount();
   1.178  	}
   1.179  	else
   1.180  	{
   1.181 -		g_VoiceMap[r][s] = params[3];
   1.182 +		g_VoiceMap[r][s] = (ListenOverride) params[3];
   1.183  	}
   1.184  
   1.185  	return 1;
   1.186 @@ -258,31 +319,61 @@
   1.187  	player = playerhelpers->GetGamePlayer(params[1]);
   1.188  	if (player == NULL)
   1.189  	{
   1.190 -		return pContext->ThrowNativeError("(Receiver) client index %d is invalid", params[1]);
   1.191 +		return pContext->ThrowNativeError("Receiver client index %d is invalid", params[1]);
   1.192  	}
   1.193  	else if (!player->IsConnected())
   1.194  	{
   1.195 -		return pContext->ThrowNativeError("(Receiver) client %d is not connected", params[1]);
   1.196 +		return pContext->ThrowNativeError("Receiver client %d is not connected", params[1]);
   1.197  	}
   1.198  
   1.199  	player = playerhelpers->GetGamePlayer(params[2]);
   1.200  	if (player == NULL)
   1.201  	{
   1.202 -		return pContext->ThrowNativeError("(Sender) client index %d is invalid", params[2]);
   1.203 +		return pContext->ThrowNativeError("Sender client index %d is invalid", params[2]);
   1.204  	}
   1.205  	else if (!player->IsConnected())
   1.206  	{
   1.207 -		return pContext->ThrowNativeError("(Sender) client %d is not connected", params[2]);
   1.208 +		return pContext->ThrowNativeError("Sender client %d is not connected", params[2]);
   1.209  	}
   1.210  
   1.211  	return g_VoiceMap[params[1]][params[2]];
   1.212  }
   1.213  
   1.214 +static cell_t IsClientMuted(IPluginContext *pContext, const cell_t *params)
   1.215 +{
   1.216 +	IGamePlayer *player;
   1.217 +
   1.218 +	player = playerhelpers->GetGamePlayer(params[1]);
   1.219 +	if (player == NULL)
   1.220 +	{
   1.221 +		return pContext->ThrowNativeError("Muter client index %d is invalid", params[1]);
   1.222 +	}
   1.223 +	else if (!player->IsConnected())
   1.224 +	{
   1.225 +		return pContext->ThrowNativeError("Muter client %d is not connected", params[1]);
   1.226 +	}
   1.227 +
   1.228 +	player = playerhelpers->GetGamePlayer(params[2]);
   1.229 +	if (player == NULL)
   1.230 +	{
   1.231 +		return pContext->ThrowNativeError("Mutee client index %d is invalid", params[2]);
   1.232 +	}
   1.233 +	else if (!player->IsConnected())
   1.234 +	{
   1.235 +		return pContext->ThrowNativeError("Mutee client %d is not connected", params[2]);
   1.236 +	}
   1.237 +
   1.238 +	return g_ClientMutes[params[1]][params[2]];
   1.239 +}
   1.240 +
   1.241  sp_nativeinfo_t g_VoiceNatives[] =
   1.242  {
   1.243  	{"SetClientListeningFlags",		SetClientListeningFlags},
   1.244  	{"GetClientListeningFlags",		GetClientListeningFlags},
   1.245  	{"SetClientListening",			SetClientListening},
   1.246  	{"GetClientListening",			GetClientListening},
   1.247 +	{"SetListenOverride",			SetClientListening},
   1.248 +	{"GetListenOverride",			GetClientListening},
   1.249 +	{"IsClientMuted",				IsClientMuted},
   1.250  	{NULL,							NULL},
   1.251  };