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: