Skip to content

Commit

Permalink
add svc_voicedata hook using rehlds
Browse files Browse the repository at this point in the history
  • Loading branch information
wootguy committed Nov 9, 2024
1 parent a3c82b5 commit fc3c82a
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 1 deletion.
1 change: 1 addition & 0 deletions dlls/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ set(HOOKS_SRC
hooks/hlds_hooks.cpp
hooks/PluginManager.cpp
hooks/rehlds.cpp
hooks/rehlds_hooks.cpp
../common/rehlds_interface.cpp
)

Expand Down
3 changes: 3 additions & 0 deletions dlls/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ cvar_t* g_psv_allow_autoaim = NULL;
cvar_t *g_footsteps = NULL;
cvar_t *g_developer = NULL;
cvar_t *sv_max_client_edicts = NULL;
cvar_t *sv_voiceenable = NULL;
cvar_t *sv_stepsize = NULL;
cvar_t *sv_lowercase = NULL;

Expand Down Expand Up @@ -280,6 +281,7 @@ void GameDLLInit( void )
g_footsteps = CVAR_GET_POINTER( "mp_footsteps" );
g_developer = CVAR_GET_POINTER( "developer" );
sv_max_client_edicts = CVAR_GET_POINTER( "sv_max_client_edicts" );
sv_voiceenable = CVAR_GET_POINTER( "sv_voiceenable" );
sv_stepsize = CVAR_GET_POINTER( "sv_stepsize" );
sv_lowercase = CVAR_GET_POINTER( "sv_lowercase" );

Expand Down Expand Up @@ -342,5 +344,6 @@ void GameDLLInit( void )
SERVER_COMMAND( "exec skill.cfg\n" );

RehldsApi_Init();
RegisterRehldsHooks();
}

1 change: 1 addition & 0 deletions dlls/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ EXPORT extern cvar_t *g_psv_allow_autoaim;
EXPORT extern cvar_t *g_footsteps;
EXPORT extern cvar_t *g_developer;
EXPORT extern cvar_t *sv_max_client_edicts;
EXPORT extern cvar_t *sv_voiceenable;
EXPORT extern cvar_t *sv_stepsize;
EXPORT extern cvar_t *sv_lowercase;

Expand Down
3 changes: 3 additions & 0 deletions dlls/hooks/PluginHooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ struct HLCOOP_PLUGIN_HOOKS {

// called after client data is updated by the mod and before it is returned to the engine
HOOK_RETURN_DATA (*pfnUpdateClientDataPost)(const edict_t* ent, int sendweapons, clientdata_t* cd);

// called before voice data is sent to a player. Set mute to true to block the message to the receiver
HOOK_RETURN_DATA (*pfnSendVoiceData)(int senderidx, int receiveridx, uint8_t* data, int sz, bool& mute);
};

EXPORT void RegisterPlugin(void* plugin, HLCOOP_PLUGIN_HOOKS* hooks, const char* name);
Expand Down
9 changes: 8 additions & 1 deletion dlls/hooks/rehlds.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,16 @@ typedef struct cache_user_s
#include "rehlds/public/rehlds/rehlds_api.h"

bool RehldsApi_Init();
void RegisterRehldsHooks();
void UnregisterRehldsHooks();

EXPORT extern IRehldsApi* g_RehldsApi;
EXPORT extern const RehldsFuncs_t* g_RehldsFuncs;
EXPORT extern IRehldsServerData* g_RehldsData;
EXPORT extern IRehldsHookchains* g_RehldsHookchains;
EXPORT extern IRehldsServerStatic* g_RehldsSvs;
EXPORT extern IRehldsServerStatic* g_RehldsSvs;

// can send network messages larger than 512 bytes (SVC_VOICEDATA)
// msgMode = MSG_BROADCAST or MSG_ONE_UNRELIABLE
// entindex = 1-based player index
EXPORT void rehlds_SendBigMessage(int msgMode, int msgType, void* data, int sz, int playerindex);
107 changes: 107 additions & 0 deletions dlls/hooks/rehlds_hooks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include "rehlds.h"
#include "util.h"
#include "PluginManager.h"

void rehlds_SendBigMessage_internal(int msgType, void* data, int sz, int playerindex) {
IGameClient* dstClient = g_RehldsSvs->GetClient(playerindex - 1);
sizebuf_t* dstDatagram = dstClient->GetDatagram();

if (dstDatagram->cursize + sz + 3 >= dstDatagram->maxsize) {
ALERT(at_error, "Message %s too large: %d\n", msgTypeStr(msgType), sz);
return;
}

g_RehldsFuncs->MSG_WriteByte(dstDatagram, msgType);
g_RehldsFuncs->MSG_WriteBuf(dstDatagram, sz, data);
}

void rehlds_SendBigMessage(int msgMode, int msgType, void* data, int sz, int playerindex) {
if (!g_RehldsFuncs) {
ALERT(at_console, "Rehlds API not initialized!\n");
return;
}

if (msgMode != MSG_BROADCAST) {
if (playerindex > 0 && playerindex <= gpGlobals->maxClients)
rehlds_SendBigMessage_internal(msgType, data, sz, playerindex);
return;
}

for (int i = 1; i <= gpGlobals->maxClients; i++) {
CBasePlayer* plr = UTIL_PlayerByIndex(i);
if (plr)
rehlds_SendBigMessage_internal(msgType, data, sz, i);
}
}

void SV_ParseVoiceData_hlcoop(IGameClient* cl) {
uint8_t chReceived[4096];
unsigned int nDataLength = g_RehldsFuncs->MSG_ReadShort();

if (nDataLength > sizeof(chReceived)) {
g_RehldsFuncs->DropClient(cl, FALSE, "Invalid voice data\n");
return;
}

g_RehldsFuncs->MSG_ReadBuf(nDataLength, chReceived);

if (sv_voiceenable->value == 0.0f)
return;

int sender = cl->GetId();
for (int i = 1; i <= gpGlobals->maxClients; i++)
{
CBasePlayer* plr = UTIL_PlayerByIndex(i);

if (!plr || !g_engfuncs.pfnVoice_GetClientListening(i, sender+1)) {
continue;
}

bool pluginWantsMute = false;

CALL_HOOKS_VOID(pfnSendVoiceData, sender + 1, i, chReceived, nDataLength, pluginWantsMute);

if (pluginWantsMute) {
continue;
}

IGameClient* dstClient = g_RehldsSvs->GetClient(i - 1);
sizebuf_t* dstDatagram = dstClient->GetDatagram();

int nSendLength = nDataLength;
if (sender + 1 == i && !dstClient->GetLoopback()) // voice_loopback
nSendLength = 0;

if (dstDatagram->cursize + nSendLength + 6 < dstDatagram->maxsize) {
g_RehldsFuncs->MSG_WriteByte(dstDatagram, SVC_VOICEDATA);
g_RehldsFuncs->MSG_WriteByte(dstDatagram, sender);
g_RehldsFuncs->MSG_WriteShort(dstDatagram, nSendLength);
g_RehldsFuncs->MSG_WriteBuf(dstDatagram, nSendLength, chReceived);
}
}
}

void Rehlds_HandleNetCommand(IRehldsHook_HandleNetCommand* chain, IGameClient* cl, uint8_t opcode) {
const int clc_voicedata = 8;

if (opcode == clc_voicedata) {
SV_ParseVoiceData_hlcoop(cl);
return;
}

chain->callNext(cl, opcode);
}

void RegisterRehldsHooks() {
if (!g_RehldsHookchains) {
return;
}
g_RehldsHookchains->HandleNetCommand()->registerHook(&Rehlds_HandleNetCommand, HC_PRIORITY_DEFAULT + 1);
}

void UnregisterRehldsHooks() {
if (!g_RehldsHookchains) {
return;
}
g_RehldsHookchains->HandleNetCommand()->unregisterHook(&Rehlds_HandleNetCommand);
}

0 comments on commit fc3c82a

Please sign in to comment.