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 };