Add IsClientTalking

This commit is contained in:
BotoX 2019-09-01 16:17:32 +02:00
parent d2905c03eb
commit cfbaf18f66
4 changed files with 128 additions and 30 deletions

View File

@ -10,7 +10,9 @@ project = SM.HL2Project(builder, projectName + '.ext')
project.sources += [ project.sources += [
'extension.cpp', 'extension.cpp',
'ringbuffer.cpp', 'ringbuffer.cpp',
'../../public/smsdk_ext.cpp' '../../public/smsdk_ext.cpp',
'../../public/CDetour/detours.cpp',
'../../public/asm/asm.c',
] ]
for sdk_name in SM.sdks: for sdk_name in SM.sdks:

View File

@ -43,6 +43,7 @@
#include <iserver.h> #include <iserver.h>
#include <ISDKTools.h> #include <ISDKTools.h>
#include "CDetour/detours.h"
#include "extension.h" #include "extension.h"
ConVar g_SmVoiceAddr("sm_voice_addr", "127.0.0.1", FCVAR_PROTECTED, "Voice server listen ip address."); ConVar g_SmVoiceAddr("sm_voice_addr", "127.0.0.1", FCVAR_PROTECTED, "Voice server listen ip address.");
@ -58,9 +59,36 @@ template <typename T> inline T min(T a, T b) { return a<b?a:b; }
CVoice g_Interface; CVoice g_Interface;
SMEXT_LINK(&g_Interface); SMEXT_LINK(&g_Interface);
CGlobalVars *gpGlobals = NULL;
ISDKTools *g_pSDKTools = NULL; ISDKTools *g_pSDKTools = NULL;
IServer *iserver = NULL; IServer *iserver = NULL;
SH_DECL_MANUALHOOK0(GetPlayerSlot, 0, 0, 0, int); // IClient::GetPlayerSlot
double g_fLastVoiceData[SM_MAXPLAYERS + 1];
DETOUR_DECL_STATIC4(SV_BroadcastVoiceData, void, IClient *, pClient, int, nBytes, char *, data, int64, xuid)
{
g_Interface.OnBroadcastVoiceData(pClient, nBytes, data);
DETOUR_STATIC_CALL(SV_BroadcastVoiceData)(pClient, nBytes, data, xuid);
}
#ifdef _WIN32
DETOUR_DECL_STATIC2(SV_BroadcastVoiceData_LTCG, void, char *, data, int64, xuid)
{
IClient *pClient = NULL;
int nBytes = 0;
__asm mov pClient, ecx;
__asm mov nBytes, edx;
g_Interface.OnBroadcastVoiceData(pClient, nBytes, data);
__asm mov ecx, pClient;
__asm mov edx, nBytes;
DETOUR_STATIC_CALL(SV_BroadcastVoiceData_LTCG)(data, xuid);
}
#endif
double getTime() double getTime()
{ {
@ -92,6 +120,7 @@ CVoice::CVoice()
m_pMode = NULL; m_pMode = NULL;
m_pCodec = NULL; m_pCodec = NULL;
m_VoiceDetour = NULL;
m_SV_BroadcastVoiceData = NULL; m_SV_BroadcastVoiceData = NULL;
} }
@ -114,47 +143,39 @@ bool CVoice::SDK_OnLoad(char *error, size_t maxlength, bool late)
} }
int engineVersion = g_SMAPI->GetSourceEngineBuild(); int engineVersion = g_SMAPI->GetSourceEngineBuild();
int offsPlayerSlot = 0; void *adrVoiceData = NULL;
switch (engineVersion) switch (engineVersion)
{ {
case SOURCE_ENGINE_CSGO: case SOURCE_ENGINE_CSGO:
#ifdef _WIN32 #ifdef _WIN32
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\x81\xEC\xD0\x00\x00\x00\x53\x56\x57", 12); adrVoiceData = memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\x81\xEC\xD0\x00\x00\x00\x53\x56\x57", 12);
offsPlayerSlot = 15;
#else #else
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx"); adrVoiceData = memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx");
offsPlayerSlot = 16;
#endif #endif
break; break;
case SOURCE_ENGINE_LEFT4DEAD2: case SOURCE_ENGINE_LEFT4DEAD2:
#ifdef _WIN32 #ifdef _WIN32
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\x83\xEC\x70\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\xA1\x2A\x2A\x2A\x2A\x53\x56", 23); adrVoiceData = memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\x83\xEC\x70\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\xA1\x2A\x2A\x2A\x2A\x53\x56", 23);
offsPlayerSlot = 14;
#else #else
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx"); adrVoiceData = memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx");
offsPlayerSlot = 15;
#endif #endif
break; break;
case SOURCE_ENGINE_NUCLEARDAWN: case SOURCE_ENGINE_NUCLEARDAWN:
#ifdef _WIN32 #ifdef _WIN32
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\xEC\x58\x57\x33\xFF", 14); adrVoiceData = memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\xEC\x58\x57\x33\xFF", 14);
offsPlayerSlot = 14;
#else #else
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx"); adrVoiceData = memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx");
offsPlayerSlot = 15;
#endif #endif
break; break;
case SOURCE_ENGINE_INSURGENCY: case SOURCE_ENGINE_INSURGENCY:
#ifdef _WIN32 #ifdef _WIN32
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\x83\xEC\x74\x68\x2A\x2A\x2A\x2A\x8D\x4D\xE4\xE8", 15); adrVoiceData = memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\x83\xEC\x74\x68\x2A\x2A\x2A\x2A\x8D\x4D\xE4\xE8", 15);
offsPlayerSlot = 14;
#else #else
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx"); adrVoiceData = memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx");
offsPlayerSlot = 15;
#endif #endif
break; break;
@ -164,11 +185,9 @@ bool CVoice::SDK_OnLoad(char *error, size_t maxlength, bool late)
case SOURCE_ENGINE_DODS: case SOURCE_ENGINE_DODS:
case SOURCE_ENGINE_SDK2013: case SOURCE_ENGINE_SDK2013:
#ifdef _WIN32 #ifdef _WIN32
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\xEC\x50\x83\x78\x30", 14); adrVoiceData = memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\xEC\x50\x83\x78\x30", 14);
offsPlayerSlot = 14;
#else #else
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx"); adrVoiceData = memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx");
offsPlayerSlot = 15;
#endif #endif
break; break;
@ -179,13 +198,36 @@ bool CVoice::SDK_OnLoad(char *error, size_t maxlength, bool late)
} }
dlclose(pEngineSo); dlclose(pEngineSo);
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)adrVoiceData;
if(!m_SV_BroadcastVoiceData) if(!m_SV_BroadcastVoiceData)
{ {
g_SMAPI->Format(error, maxlength, "SV_BroadcastVoiceData sigscan failed."); g_SMAPI->Format(error, maxlength, "SV_BroadcastVoiceData sigscan failed.");
return false; return false;
} }
SH_MANUALHOOK_RECONFIGURE(GetPlayerSlot, offsPlayerSlot, 0, 0); // Setup voice detour.
CDetourManager::Init(g_pSM->GetScriptingEngine(), NULL);
#ifdef _WIN32
if (engineVersion == SOURCE_ENGINE_CSGO || engineVersion == SOURCE_ENGINE_INSURGENCY)
{
m_VoiceDetour = DETOUR_CREATE_STATIC(SV_BroadcastVoiceData_LTCG, adrVoiceData);
}
else
{
m_VoiceDetour = DETOUR_CREATE_STATIC(SV_BroadcastVoiceData, adrVoiceData);
}
#else
m_VoiceDetour = DETOUR_CREATE_STATIC(SV_BroadcastVoiceData, adrVoiceData);
#endif
if (!m_VoiceDetour)
{
g_SMAPI->Format(error, maxlength, "SV_BroadcastVoiceData detour failed.");
return false;
}
m_VoiceDetour->EnableDetour();
// Init tcp server // Init tcp server
m_ListenSocket = socket(AF_INET, SOCK_STREAM, 0); m_ListenSocket = socket(AF_INET, SOCK_STREAM, 0);
@ -271,6 +313,7 @@ bool CVoice::SDK_OnLoad(char *error, size_t maxlength, bool late)
bool CVoice::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late) bool CVoice::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
{ {
GET_V_IFACE_CURRENT(GetEngineFactory, g_pCVar, ICvar, CVAR_INTERFACE_VERSION); GET_V_IFACE_CURRENT(GetEngineFactory, g_pCVar, ICvar, CVAR_INTERFACE_VERSION);
gpGlobals = ismm->GetCGlobals();
ConVar_Register(0, this); ConVar_Register(0, this);
return true; return true;
@ -282,8 +325,37 @@ bool CVoice::RegisterConCommandBase(ConCommandBase *pVar)
return META_REGCVAR(pVar); return META_REGCVAR(pVar);
} }
cell_t IsClientTalking(IPluginContext *pContext, const cell_t *params)
{
int client = params[1];
if(client < 1 || client > SM_MAXPLAYERS)
{
return pContext->ThrowNativeError("Client index %d is invalid", client);
}
double d = gpGlobals->curtime - g_fLastVoiceData[client];
if(d < 0) // mapchange
return false;
if(d > 0.33)
return false;
return true;
}
const sp_nativeinfo_t MyNatives[] =
{
{ "IsClientTalking", IsClientTalking },
{ NULL, NULL }
};
void CVoice::SDK_OnAllLoaded() void CVoice::SDK_OnAllLoaded()
{ {
sharesys->AddNatives(myself, MyNatives);
sharesys->RegisterLibrary(myself, "Voice");
SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools); SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools);
if(g_pSDKTools == NULL) if(g_pSDKTools == NULL)
smutils->LogError(myself, "SDKTools interface not found"); smutils->LogError(myself, "SDKTools interface not found");
@ -297,6 +369,12 @@ void CVoice::SDK_OnUnload()
{ {
smutils->RemoveGameFrameHook(::OnGameFrame); smutils->RemoveGameFrameHook(::OnGameFrame);
if(m_VoiceDetour)
{
m_VoiceDetour->Destroy();
m_VoiceDetour = NULL;
}
if(m_ListenSocket != -1) if(m_ListenSocket != -1)
{ {
close(m_ListenSocket); close(m_ListenSocket);
@ -325,6 +403,13 @@ void CVoice::OnGameFrame(bool simulating)
HandleVoiceData(); HandleVoiceData();
} }
void CVoice::OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data)
{
int client = pClient->GetPlayerSlot() + 1;
g_fLastVoiceData[client] = gpGlobals->curtime;
}
void CVoice::HandleNetwork() void CVoice::HandleNetwork()
{ {
if(m_ListenSocket == -1) if(m_ListenSocket == -1)
@ -553,7 +638,7 @@ void CVoice::HandleVoiceData()
} }
} }
SV_BroadcastVoiceData(pClient, FinalSize, aFinal); BroadcastVoiceData(pClient, FinalSize, aFinal);
} }
if(m_AvailableTime < getTime()) if(m_AvailableTime < getTime())
@ -562,7 +647,14 @@ void CVoice::HandleVoiceData()
m_AvailableTime += (double)FramesAvailable * m_EncoderSettings.FrameTime; m_AvailableTime += (double)FramesAvailable * m_EncoderSettings.FrameTime;
} }
void CVoice::SV_BroadcastVoiceData(IClient *pClient, int nBytes, unsigned char *pData) void CVoice::BroadcastVoiceData(IClient *pClient, int nBytes, unsigned char *pData)
{ {
m_SV_BroadcastVoiceData(pClient, nBytes, pData, 0); #ifdef _WIN32
__asm mov ecx, pClient;
__asm mov edx, nBytes;
DETOUR_STATIC_CALL(SV_BroadcastVoiceData_LTCG)((char *)pData, 0);
#else
DETOUR_STATIC_CALL(SV_BroadcastVoiceData)(pClient, nBytes, (char *)pData, 0);
#endif
} }

View File

@ -32,6 +32,7 @@
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ #ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ #define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
#include <poll.h>
#include "smsdk_ext.h" #include "smsdk_ext.h"
#include "celt_header.h" #include "celt_header.h"
#include "ringbuffer.h" #include "ringbuffer.h"
@ -49,6 +50,7 @@ typedef __int64 int64;
typedef long long int64; typedef long long int64;
#endif #endif
class CDetour;
class IClient; class IClient;
typedef void (*t_SV_BroadcastVoiceData)(IClient *, int, unsigned char *, int64); typedef void (*t_SV_BroadcastVoiceData)(IClient *, int, unsigned char *, int64);
@ -135,6 +137,7 @@ public: // IConCommandBaseAccessor
public: public:
CVoice(); CVoice();
void OnGameFrame(bool simulating); void OnGameFrame(bool simulating);
void OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data);
private: private:
int m_ListenSocket; int m_ListenSocket;
@ -169,11 +172,12 @@ private:
CELTEncoder *m_pCodec; CELTEncoder *m_pCodec;
t_SV_BroadcastVoiceData m_SV_BroadcastVoiceData; t_SV_BroadcastVoiceData m_SV_BroadcastVoiceData;
CDetour *m_VoiceDetour;
void HandleNetwork(); void HandleNetwork();
void OnDataReceived(CClient *pClient, int16_t *pData, size_t Samples); void OnDataReceived(CClient *pClient, int16_t *pData, size_t Samples);
void HandleVoiceData(); void HandleVoiceData();
void SV_BroadcastVoiceData(IClient *pClient, int nBytes, unsigned char *pData); void BroadcastVoiceData(IClient *pClient, int nBytes, unsigned char *pData);
}; };
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ #endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_

View File

@ -40,7 +40,7 @@
/* Basic information exposed publicly */ /* Basic information exposed publicly */
#define SMEXT_CONF_NAME "Voice" #define SMEXT_CONF_NAME "Voice"
#define SMEXT_CONF_DESCRIPTION "Inject voice data over existing clients" #define SMEXT_CONF_DESCRIPTION "Inject voice data over existing clients"
#define SMEXT_CONF_VERSION "1.0" #define SMEXT_CONF_VERSION "1.1"
#define SMEXT_CONF_AUTHOR "BotoX" #define SMEXT_CONF_AUTHOR "BotoX"
#define SMEXT_CONF_URL "" #define SMEXT_CONF_URL ""
#define SMEXT_CONF_LOGTAG "VOICE" #define SMEXT_CONF_LOGTAG "VOICE"
@ -61,7 +61,7 @@
/** Enable interfaces you want to use here by uncommenting lines */ /** Enable interfaces you want to use here by uncommenting lines */
//#define SMEXT_ENABLE_FORWARDSYS //#define SMEXT_ENABLE_FORWARDSYS
//#define SMEXT_ENABLE_HANDLESYS //#define SMEXT_ENABLE_HANDLESYS
//#define SMEXT_ENABLE_PLAYERHELPERS #define SMEXT_ENABLE_PLAYERHELPERS
//#define SMEXT_ENABLE_DBMANAGER //#define SMEXT_ENABLE_DBMANAGER
#define SMEXT_ENABLE_GAMECONF #define SMEXT_ENABLE_GAMECONF
#define SMEXT_ENABLE_MEMUTILS #define SMEXT_ENABLE_MEMUTILS