diff --git a/extensions/sdktools/Makefile b/extensions/sdktools/Makefile index c72baa2b..3023bc40 100644 --- a/extensions/sdktools/Makefile +++ b/extensions/sdktools/Makefile @@ -15,7 +15,8 @@ PROJECT = sdktools LINK_HL2 = $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so tier0_i486.so OBJECTS = sdk/smsdk_ext.cpp extension.cpp gamerules.cpp vdecoder.cpp vcallbuilder.cpp \ - vcaller.cpp vnatives.cpp vsound.cpp tenatives.cpp trnatives.cpp tempents.cpp vstringtable.cpp vhelpers.cpp + vcaller.cpp vnatives.cpp vsound.cpp tenatives.cpp trnatives.cpp tempents.cpp vstringtable.cpp \ + vhelpers.cpp voice.cpp ############################################## ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### diff --git a/extensions/sdktools/extension.cpp b/extensions/sdktools/extension.cpp index e0027854..03fbbee0 100644 --- a/extensions/sdktools/extension.cpp +++ b/extensions/sdktools/extension.cpp @@ -54,6 +54,7 @@ IGameHelpers *g_pGameHelpers = NULL; IServerGameClients *serverClients = NULL; HandleType_t g_CallHandle = 0; HandleType_t g_TraceHandle = 0; +IVoiceServer *voiceserver = NULL; SMEXT_LINK(&g_SdkTools); @@ -61,6 +62,7 @@ extern sp_nativeinfo_t g_CallNatives[]; extern sp_nativeinfo_t g_TENatives[]; extern sp_nativeinfo_t g_TRNatives[]; extern sp_nativeinfo_t g_StringTableNatives[]; +extern sp_nativeinfo_t g_VoiceNatives[]; bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late) { @@ -71,6 +73,7 @@ bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late) sharesys->AddNatives(myself, g_SoundNatives); sharesys->AddNatives(myself, g_TRNatives); sharesys->AddNatives(myself, g_StringTableNatives); + sharesys->AddNatives(myself, g_VoiceNatives); SM_GET_IFACE(GAMEHELPERS, g_pGameHelpers); @@ -79,6 +82,7 @@ bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late) return false; } + playerhelpers->AddClientListener(&g_SdkTools); g_CallHandle = handlesys->CreateType("ValveCall", this, 0, NULL, NULL, myself->GetIdentity(), NULL); g_TraceHandle = handlesys->CreateType("TraceRay", this, 0, NULL, NULL, myself->GetIdentity(), NULL); @@ -116,6 +120,7 @@ void SDKTools::SDK_OnUnload() g_TEManager.Shutdown(); gameconfs->CloseGameConfigFile(g_pGameConf); + playerhelpers->RemoveClientListener(&g_SdkTools); } bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late) @@ -126,6 +131,7 @@ bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool GET_V_IFACE_ANY(engineFactory, netstringtables, INetworkStringTableContainer, INTERFACENAME_NETWORKSTRINGTABLESERVER); GET_V_IFACE_ANY(engineFactory, pluginhelpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS); GET_V_IFACE_ANY(serverFactory, serverClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS); + GET_V_IFACE_ANY(engineFactory, voiceserver, IVoiceServer, INTERFACEVERSION_VOICESERVER); return true; } diff --git a/extensions/sdktools/extension.h b/extensions/sdktools/extension.h index 6a3ca6bb..37bf6dac 100644 --- a/extensions/sdktools/extension.h +++ b/extensions/sdktools/extension.h @@ -44,6 +44,7 @@ #include #include #include +#include #include /** @@ -53,7 +54,8 @@ class SDKTools : public SDKExtension, public IHandleTypeDispatch, - public IConCommandBaseAccessor + public IConCommandBaseAccessor, + public IClientListener { public: //public IHandleTypeDispatch void OnHandleDestroy(HandleType_t type, void *object); @@ -73,8 +75,13 @@ public: #endif public: //IConCommandBaseAccessor bool RegisterConCommandBase(ConCommandBase *pVar); +public: //IClientListner + void OnClientDisconnecting(int client); +public: // IVoiceServer + bool OnSetClientListening(int iReceiver, int iSender, bool bListen); }; +extern SDKTools g_SdkTools; /* Interfaces from engine or gamedll */ extern IServerGameEnts *gameents; extern IEngineTrace *enginetrace; @@ -82,6 +89,7 @@ extern IEngineSound *engsound; extern INetworkStringTableContainer *netstringtables; extern IServerPluginHelpers *pluginhelpers; extern IServerGameClients *serverClients; +extern IVoiceServer *voiceserver; /* Interfaces from SourceMod */ extern IBinTools *g_pBinTools; extern IGameConfig *g_pGameConf; diff --git a/extensions/sdktools/msvc8/sdktools.vcproj b/extensions/sdktools/msvc8/sdktools.vcproj index 37f469e7..ba77f491 100644 --- a/extensions/sdktools/msvc8/sdktools.vcproj +++ b/extensions/sdktools/msvc8/sdktools.vcproj @@ -223,6 +223,10 @@ RelativePath="..\vnatives.cpp" > + + diff --git a/extensions/sdktools/voice.cpp b/extensions/sdktools/voice.cpp new file mode 100644 index 00000000..010e579f --- /dev/null +++ b/extensions/sdktools/voice.cpp @@ -0,0 +1,122 @@ +#include + +#define SPEAK_NORMAL 0 +#define SPEAK_MUTED 1 +#define SPEAK_ALL 2 +#define SPEAK_LISTENALL 4 + +size_t g_VoiceFlags[65]; +size_t g_VoiceFlagsCount = 0; + +SH_DECL_HOOK3(IVoiceServer, SetClientListening, SH_NOATTRIB, 0, bool, int, int, bool); + +bool SDKTools::OnSetClientListening(int iReceiver, int iSender, bool bListen) +{ + if (g_VoiceFlags[iSender] & SPEAK_MUTED) + { + RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, false)); + } + + if (g_VoiceFlags[iSender] & SPEAK_ALL) + { + RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, true)); + } + + if (g_VoiceFlags[iReceiver] & SPEAK_LISTENALL) + { + RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, true)); + } + + RETURN_META_VALUE(MRES_IGNORED, bListen); +} + +void SDKTools::OnClientDisconnecting(int client) +{ + if (g_VoiceFlags[client]) + { + g_VoiceFlags[client] = 0; + if (!--g_VoiceFlagsCount) + { + SH_REMOVE_HOOK_MEMFUNC(IVoiceServer, SetClientListening, voiceserver, &g_SdkTools, &SDKTools::OnSetClientListening, false); + } + } +} + +static cell_t SetClientListeningFlags(IPluginContext *pContext, const cell_t *params) +{ + IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]); + if (player == NULL) + { + return pContext->ThrowNativeError("Client index %d is invalid", params[1]); + } else if (!player->IsConnected()) { + return pContext->ThrowNativeError("Client %d is not connected", params[1]); + } + + if (!params[2] && g_VoiceFlags[params[1]]) + { + if (!--g_VoiceFlagsCount) + { + SH_REMOVE_HOOK_MEMFUNC(IVoiceServer, SetClientListening, voiceserver, &g_SdkTools, &SDKTools::OnSetClientListening, false); + } + } else if (!g_VoiceFlags[params[1]] && params[2]) { + + if (!g_VoiceFlagsCount++) + { + SH_ADD_HOOK_MEMFUNC(IVoiceServer, SetClientListening, voiceserver, &g_SdkTools, &SDKTools::OnSetClientListening, false); + } + } + + g_VoiceFlags[params[1]] = params[2]; + + return 1; +} + +static cell_t GetClientListeningFlags(IPluginContext *pContext, const cell_t *params) +{ + IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]); + if (player == NULL) + { + return pContext->ThrowNativeError("Client index %d is invalid", params[1]); + } else if (!player->IsConnected()) { + return pContext->ThrowNativeError("Client %d is not connected", params[1]); + } + + return g_VoiceFlags[params[1]]; +} + +static cell_t SetClientListening(IPluginContext *pContext, const cell_t *params) +{ + IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]); + if (player == NULL) + { + return pContext->ThrowNativeError("Client index %d is invalid", params[1]); + } else if (!player->IsConnected()) { + return pContext->ThrowNativeError("Client %d is not connected", params[1]); + } + + bool bListen = !params[3] ? false : true; + + return voiceserver->SetClientListening(params[1], params[2], bListen) ? 1 : 0; +} + +static cell_t GetClientListening(IPluginContext *pContext, const cell_t *params) +{ + IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]); + if (player == NULL) + { + return pContext->ThrowNativeError("Client index %d is invalid", params[1]); + } else if (!player->IsConnected()) { + return pContext->ThrowNativeError("Client %d is not connected", params[1]); + } + + return voiceserver->GetClientListening(params[1], params[2]) ? 1 : 0; +} + +sp_nativeinfo_t g_VoiceNatives[] = +{ + {"SetClientListeningFlags", SetClientListeningFlags}, + {"GetClientListeningFlags", GetClientListeningFlags}, + {"SetClientListening", SetClientListening}, + {"GetClientListening", GetClientListening}, + {NULL, NULL}, +}; diff --git a/plugins/include/sdktools.inc b/plugins/include/sdktools.inc index a68dd805..272e5194 100644 --- a/plugins/include/sdktools.inc +++ b/plugins/include/sdktools.inc @@ -28,6 +28,7 @@ #include #include #include +#include enum SDKCallType { diff --git a/plugins/include/sdktools_voice.inc b/plugins/include/sdktools_voice.inc new file mode 100644 index 00000000..24d12516 --- /dev/null +++ b/plugins/include/sdktools_voice.inc @@ -0,0 +1,66 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This file is part of the SourceMod/SourcePawn SDK. This file may only be used + * or modified under the Terms and Conditions of its License Agreement, which is found + * in LICENSE.txt. The Terms and Conditions for making SourceMod extensions/plugins + * may change at any time. To view the latest information, see: + * http://www.sourcemod.net/license.php + * + * + */ + +#if defined _sdktools_voice_included + #endinput +#endif +#define _sdktools_voice_included + +/** + * @section voice flags. + */ +#define VOICE_NORMAL 0 /**< Allow the client to listen and speak normally. */ +#define VOICE_MUTED 1 /**< Mutes the client from speaking to everyone. */ +#define VOICE_SPEAKALL 2 /**< Allow the client to speak to everyone. */ +#define VOICE_LISTENALL 4 /**< Allow the client to listen to everyone. */ + +/** + * @endsection + */ + +/** + * Set the client listening flags. + * + * @param client The client index + * @param flags The voice flags + * @noreturn + */ +native SetClientListeningFlags(client, flags); + +/** + * Retrieve the client current listening flags. + * + * @param client The client index + * @return The current voice flags + */ +native GetClientListeningFlags(client); + +/** + * Set the receiver ability to listen to the sender. + * + * @param iReceiver The listener index. + * @param iSender The sender index. + * @return True if successful otherwise false. + */ +native bool:SetClientListening(iReceiver, iSender, bool:bListen); + +/** + * Retrieves if the receiver can listen to the sender. + * + * @param iReceiver The listener index. + * @param iSender The sender index. + * @return True if successful otherwise false. + */ +native bool:GetClientListening(iReceiver, iSender); \ No newline at end of file