diff --git a/revoice/msvc/ReVoice.vcxproj b/revoice/msvc/ReVoice.vcxproj index 02c7638..36e956c 100644 --- a/revoice/msvc/ReVoice.vcxproj +++ b/revoice/msvc/ReVoice.vcxproj @@ -31,6 +31,7 @@ + @@ -50,6 +51,8 @@ + + diff --git a/revoice/msvc/ReVoice.vcxproj.filters b/revoice/msvc/ReVoice.vcxproj.filters index 1f19588..f9c453d 100644 --- a/revoice/msvc/ReVoice.vcxproj.filters +++ b/revoice/msvc/ReVoice.vcxproj.filters @@ -90,6 +90,9 @@ src + + src + @@ -134,5 +137,11 @@ src + + src + + + src + \ No newline at end of file diff --git a/revoice/src/VoiceEncoder_Silk.h b/revoice/src/VoiceEncoder_Silk.h index aaf6741..7ee234d 100644 --- a/revoice/src/VoiceEncoder_Silk.h +++ b/revoice/src/VoiceEncoder_Silk.h @@ -4,27 +4,27 @@ #include "utlbuffer.h" #include "SKP_Silk_SDK_API.h" -class VoiceEncoder_Silk : public IVoiceCodec { -private: - void * m_pEncoder; /* 4 4 */ - int m_API_fs_Hz; /* 8 4 */ - int m_targetRate_bps; /* 12 4 */ - int m_packetLoss_perc; /* 16 4 */ - SKP_SILK_SDK_EncControlStruct m_encControl; /* 20 32 */ - CUtlBuffer m_bufOverflowBytes; /* 52 24 */ - - void * m_pDecoder; /* 76 4 */ - SKP_SILK_SDK_DecControlStruct m_decControl; /* 80 20 */ - -public: - VoiceEncoder_Silk(); - - virtual ~VoiceEncoder_Silk(); - - virtual bool Init(int quality); - virtual void Release(); - virtual bool ResetState(); - virtual int Compress(const char *pUncompressedBytes, int nSamples, char *pCompressed, int maxCompressedBytes, bool bFinal); - virtual int Decompress(const char *pCompressed, int compressedBytes, char *pUncompressed, int maxUncompressedBytes); - +class VoiceEncoder_Silk : public IVoiceCodec { +private: + void * m_pEncoder; /* 4 4 */ + int m_API_fs_Hz; /* 8 4 */ + int m_targetRate_bps; /* 12 4 */ + int m_packetLoss_perc; /* 16 4 */ + SKP_SILK_SDK_EncControlStruct m_encControl; /* 20 32 */ + CUtlBuffer m_bufOverflowBytes; /* 52 24 */ + + void * m_pDecoder; /* 76 4 */ + SKP_SILK_SDK_DecControlStruct m_decControl; /* 80 20 */ + +public: + VoiceEncoder_Silk(); + + virtual ~VoiceEncoder_Silk(); + + virtual bool Init(int quality); + virtual void Release(); + virtual bool ResetState(); + virtual int Compress(const char *pUncompressedBytes, int nSamples, char *pCompressed, int maxCompressedBytes, bool bFinal); + virtual int Decompress(const char *pCompressed, int compressedBytes, char *pUncompressed, int maxUncompressedBytes); + }; /* size: 100 */ \ No newline at end of file diff --git a/revoice/src/VoiceEncoder_Speex.h b/revoice/src/VoiceEncoder_Speex.h index b1d03b2..b5e2f66 100644 --- a/revoice/src/VoiceEncoder_Speex.h +++ b/revoice/src/VoiceEncoder_Speex.h @@ -5,7 +5,7 @@ #include "speex.h" /* <61c> ../engine/voice_codecs/speex/VoiceEncoder_Speex.h:57 */ -class VoiceEncoder_Speex: IFrameEncoder { +class VoiceEncoder_Speex: public IFrameEncoder { protected: virtual ~VoiceEncoder_Speex(); diff --git a/revoice/src/dllapi.cpp b/revoice/src/dllapi.cpp index df9c71f..ce55546 100644 --- a/revoice/src/dllapi.cpp +++ b/revoice/src/dllapi.cpp @@ -51,7 +51,7 @@ static DLL_FUNCTIONS gFunctionTable = NULL, // pfnRestoreGlobalState NULL, // pfnResetGlobalState - NULL, // pfnClientConnect + &mm_ClientConnect, NULL, // pfnClientDisconnect NULL, // pfnClientKill NULL, // pfnClientPutInServer @@ -95,6 +95,15 @@ static DLL_FUNCTIONS gFunctionTable = NULL, // pfnAllowLagCompensation }; +static NEW_DLL_FUNCTIONS gNewFunctionTable = { + NULL, //pfnOnFreeEntPrivateData + NULL, //pfnGameShutdown + NULL, //pfnShouldCollide + NULL, //pfnCvarValue + &mm_CvarValue2, //pfnCvarValue2 +}; + + C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { if(!pFunctionTable) { @@ -109,4 +118,19 @@ C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersi } memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS)); return(TRUE); +} + +C_DLLEXPORT int GetNewDLLFunctions(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion) { + if (!pNewFunctionTable) { + UTIL_LogPrintf("GetNewDLLFunctions called with null pNewFunctionTable"); + return(FALSE); + } + else if (*interfaceVersion != NEW_DLL_FUNCTIONS_VERSION) { + UTIL_LogPrintf("GetNewDLLFunctions version mismatch; requested=%d ours=%d", *interfaceVersion, NEW_DLL_FUNCTIONS_VERSION); + //! Tell metamod what version we had, so it can figure out who is out of date. + *interfaceVersion = NEW_DLL_FUNCTIONS_VERSION; + return(FALSE); + } + memcpy(pNewFunctionTable, &gNewFunctionTable, sizeof(NEW_DLL_FUNCTIONS)); + return(TRUE); } \ No newline at end of file diff --git a/revoice/src/meta_api.cpp b/revoice/src/meta_api.cpp index 09efd01..ba4c219 100644 --- a/revoice/src/meta_api.cpp +++ b/revoice/src/meta_api.cpp @@ -42,7 +42,7 @@ static META_FUNCTIONS gMetaFunctionTable = { NULL, // pfnGetEntityAPI_Post META; called after game DLL &GetEntityAPI2, // pfnGetEntityAPI2 HL SDK2; called before game DLL NULL, // pfnGetEntityAPI2_Post META; called after game DLL - NULL, // pfnGetNewDLLFunctions HL SDK2; called before game DLL + &GetNewDLLFunctions, // pfnGetNewDLLFunctions HL SDK2; called before game DLL NULL, // pfnGetNewDLLFunctions_Post META; called after game DLL NULL, // pfnGetEngineFunctions META; called before HL engine NULL, // pfnGetEngineFunctions_Post META; called after HL engine diff --git a/revoice/src/precompiled.h b/revoice/src/precompiled.h index 2bc7ffb..3e3974d 100644 --- a/revoice/src/precompiled.h +++ b/revoice/src/precompiled.h @@ -1,3 +1,5 @@ +#pragma once + #include "osconf.h" #include "sys_shared.h" #include "crc32c.h" @@ -19,6 +21,8 @@ #include "VoiceEncoder_Silk.h" #include "VoiceEncoder_Speex.h" #include "voice_codec_frame.h" +#include "revoice_player.h" +#include "revoice_main.h" #include "interface.h" -#include "utlbuffer.h" +#include "utlbuffer.h" diff --git a/revoice/src/revoice_main.cpp b/revoice/src/revoice_main.cpp new file mode 100644 index 0000000..ef1f177 --- /dev/null +++ b/revoice/src/revoice_main.cpp @@ -0,0 +1,56 @@ + +#include "precompiled.h" + +int g_ClientBeingConnected_Protocol = 0; + +void SV_ConnectClient_hook(IRehldsHook_SV_ConnectClient* chain) { + g_ClientBeingConnected_Protocol = atoi(g_engfuncs.pfnCmd_Argv(1)); + chain->callNext(); +} + +void Rehlds_ClientConnected_Hook(IRehldsHook_ClientConnected* chain, IGameClient* cl) { + if (g_ClientBeingConnected_Protocol >= 47 && g_ClientBeingConnected_Protocol <= 48) { + CRevoicePlayer* plr = GetPlayerByClientPtr(cl); + plr->OnConnected(g_ClientBeingConnected_Protocol); + + if (g_ClientBeingConnected_Protocol == 47) { + plr->InitVoice(vct_speex); + } else { + g_engfuncs.pfnQueryClientCvarValue2(cl->GetEdict(), "sv_version", 0); + } + } + + chain->callNext(cl); +} + +void mm_CvarValue2(const edict_t *pEnt, int requestID, const char *cvarName, const char *value) { + if (!strcmp("sv_version", cvarName)) { + // ] sv_version + // "sv_version" is "1.1.2.1/2.0.0.0,48,4554" + + const char* lastSeparator = strrchr(cvarName, ','); + int buildNumber = 0; + if (lastSeparator) { + buildNumber = atoi(lastSeparator + 1); + } + + CRevoicePlayer* plr = GetPlayerByEdict(pEnt); + if (buildNumber > 4554) { + plr->InitVoice(vct_silk); + } else { + plr->InitVoice(vct_speex); + } + } + + RETURN_META(MRES_IGNORED); +} + +qboolean mm_ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) { + RETURN_META_VALUE(MRES_IGNORED, 1); +} + +bool Revoice_Main_Init() { + g_RehldsHookchains->SV_ConnectClient()->registerHook(SV_ConnectClient_hook); + g_RehldsHookchains->ClientConnected()->registerHook(Rehlds_ClientConnected_Hook); + return true; +} \ No newline at end of file diff --git a/revoice/src/revoice_main.h b/revoice/src/revoice_main.h new file mode 100644 index 0000000..b0c2daf --- /dev/null +++ b/revoice/src/revoice_main.h @@ -0,0 +1,9 @@ +#pragma once + +#include "revoice_shared.h" +#include "revoice_player.h" + +extern qboolean mm_ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]); +extern void mm_CvarValue2(const edict_t *pEnt, int requestID, const char *cvarName, const char *value); + +extern bool Revoice_Main_Init(); diff --git a/revoice/src/revoice_player.cpp b/revoice/src/revoice_player.cpp new file mode 100644 index 0000000..74251ab --- /dev/null +++ b/revoice/src/revoice_player.cpp @@ -0,0 +1,52 @@ + +#include "precompiled.h" + +CRevoicePlayer g_Players[MAX_PLAYERS]; + +CRevoicePlayer::CRevoicePlayer() { + m_CodecType = vct_none; + m_SpeexCodec = new VoiceCodec_Frame(new VoiceEncoder_Speex()); + m_SilkCodec = new VoiceEncoder_Silk(); + + m_SpeexCodec->Init(5); + m_SilkCodec->Init(5); + + m_RehldsClient = NULL; + m_Protocol = 0; +} + +void CRevoicePlayer::Initialize(IGameClient* cl) { + m_RehldsClient = cl; +} + +void CRevoicePlayer::InitVoice(revoice_codec_type codecType) { + m_CodecType = codecType; + m_SilkCodec->ResetState(); + m_SpeexCodec->ResetState(); +} + +void CRevoicePlayer::OnConnected(int protocol) { + m_Protocol = protocol; + m_CodecType = vct_none; +} + +void Revoice_Init_Players() { + int maxclients = g_RehldsSvs->GetMaxClients(); + + for (int i = 0; i < maxclients; i++) { + g_Players[i].Initialize(g_RehldsSvs->GetClient(i)); + } +} + +CRevoicePlayer* GetPlayerByClientPtr(IGameClient* cl) { + return &g_Players[cl->GetId()]; +} + +CRevoicePlayer* GetPlayerByEdict(const edict_t* ed) { + int clientId = g_engfuncs.pfnIndexOfEdict(ed) - 1; + if (clientId < 0 || clientId >= g_RehldsSvs->GetMaxClients()) { + util_syserror("Invalid player edict id=%d\n", clientId); + } + + return &g_Players[clientId]; +} \ No newline at end of file diff --git a/revoice/src/revoice_player.h b/revoice/src/revoice_player.h index 028a364..2400b96 100644 --- a/revoice/src/revoice_player.h +++ b/revoice/src/revoice_player.h @@ -1,10 +1,29 @@ +#pragma once #include "revoice_shared.h" #include "VoiceEncoder_Silk.h" +#include "VoiceEncoder_Speex.h" +#include "voice_codec_frame.h" class CRevoicePlayer { private: + IGameClient* m_RehldsClient; revoice_codec_type m_CodecType; VoiceEncoder_Silk* m_SilkCodec; - IVoiceCodec* m_SpeexCodec; -}; \ No newline at end of file + VoiceCodec_Frame* m_SpeexCodec; + int m_Protocol; + +public: + CRevoicePlayer(); + void Initialize(IGameClient* cl); + void OnConnected(int protocol); + void InitVoice(revoice_codec_type codecType); + + +}; + +extern CRevoicePlayer g_Players[MAX_PLAYERS]; + +extern void Revoice_Init_Players(); +extern CRevoicePlayer* GetPlayerByClientPtr(IGameClient* cl); +extern CRevoicePlayer* GetPlayerByEdict(const edict_t* ed); diff --git a/revoice/src/voice_codec_frame.h b/revoice/src/voice_codec_frame.h index 75407a8..e4ccdc4 100644 --- a/revoice/src/voice_codec_frame.h +++ b/revoice/src/voice_codec_frame.h @@ -1,5 +1,8 @@ #pragma once +#include "IVoiceCodec.h" +#include "iframeencoder.h" + /* <19b1> ../engine/voice_codecs/speex/../frame_encoder/voice_codec_frame.cpp:18 */ class VoiceCodec_Frame: public IVoiceCodec { public: