diff --git a/README.md b/README.md
index f58568c..1e97cb4 100644
--- a/README.md
+++ b/README.md
@@ -36,8 +36,10 @@ Bugfixed version of rehlds contains an additional cvars:
sv_auto_precache_sounds_in_models <1|0> // Automatically precache sounds attached to models. Deault: 0
sv_delayed_spray_upload <1|0> // Upload custom sprays after entering the game instead of when connecting. It increases upload speed. Default: 0
sv_echo_unknown_cmd <1|0> // Echo in the console when trying execute an uncknown command. Default: 0
+sv_rcon_condebug <1|0> // Print rcon debug in the console. Default: 1
sv_force_ent_intersection <1|0> // In a 3-rd party plugins used to force colliding of SOLID_SLIDEBOX entities. Default: 0
sv_rehlds_force_dlmax <1|0> // Force a client's cl_dlmax cvar to 1024. It avoids an excessive packets fragmentation. Default: 0
+sv_rehlds_hull_centering <1|0> // Use center of hull instead of corner. Default: 0
sv_rehlds_movecmdrate_max_avg // Max average level of 'move' cmds for ban. Default: 400
sv_rehlds_movecmdrate_max_burst // Max burst level of 'move' cmds for ban. Default: 2500
sv_rehlds_stringcmdrate_max_avg // Max average level of 'string' cmds for ban. Default: 80
diff --git a/rehlds/common/const.h b/rehlds/common/const.h
index f539684..721a8da 100644
--- a/rehlds/common/const.h
+++ b/rehlds/common/const.h
@@ -71,6 +71,9 @@
#define FL_KILLME (1<<30) // This entity is marked for death -- This allows the engine to kill ents at the appropriate time
#define FL_DORMANT (1<<31) // Entity is dormant, no updates to client
+// SV_EmitSound2 flags
+#define SND_EMIT2_NOPAS (1<<0) // never to do check PAS
+#define SND_EMIT2_INVOKER (1<<1) // do not send to the client invoker
// Engine edict->spawnflags
#define SF_NOTINDEATHMATCH 0x0800 // Do not spawn when deathmatch and loading entities from a file
diff --git a/rehlds/engine/server.h b/rehlds/engine/server.h
index 131d1fe..c0c3503 100644
--- a/rehlds/engine/server.h
+++ b/rehlds/engine/server.h
@@ -544,6 +544,7 @@ extern cvar_t sv_auto_precache_sounds_in_models;
extern cvar_t sv_delayed_spray_upload;
extern cvar_t sv_rehlds_force_dlmax;
extern cvar_t sv_rehlds_hull_centering;
+extern cvar_t sv_rcon_condebug;
#endif
extern int sv_playermodel;
diff --git a/rehlds/engine/sv_main.cpp b/rehlds/engine/sv_main.cpp
index aa07b94..183509a 100644
--- a/rehlds/engine/sv_main.cpp
+++ b/rehlds/engine/sv_main.cpp
@@ -305,6 +305,7 @@ cvar_t sv_delayed_spray_upload = { "sv_delayed_spray_upload", "0", 0, 0.0f, null
cvar_t sv_rehlds_force_dlmax = { "sv_rehlds_force_dlmax", "0", 0, 0.0f, nullptr };
cvar_t listipcfgfile = { "listipcfgfile", "listip.cfg", 0, 0.0f, nullptr };
cvar_t sv_rehlds_hull_centering = { "sv_rehlds_hull_centering", "0", 0, 0.0f, nullptr };
+cvar_t sv_rcon_condebug = { "sv_rcon_condebug", "1", 0, 1.0f, nullptr };
#endif
/* ../engine/sv_main.c:113 */
@@ -3386,7 +3387,11 @@ int SV_Rcon_Validate(void)
if (SV_CheckRconFailure(&net_from))
{
- Con_Printf("Banning %s for rcon hacking attempts\n", NET_AdrToString(net_from));
+#ifdef REHLDS_FIXES
+ if (sv_rcon_condebug.value > 0.0f)
+#endif
+ Con_Printf("Banning %s for rcon hacking attempts\n", NET_AdrToString(net_from));
+
Cbuf_AddText(va("addip %i %s\n", (int)sv_rcon_banpenalty.value, NET_BaseAdrToString(net_from)));
return 3;
}
@@ -3415,19 +3420,29 @@ void SV_Rcon(netadr_t *net_from_)
Q_memcpy(remaining, &net_message.data[Q_strlen("rcon")], len);
remaining[len] = 0;
- if (invalid)
+
+#ifndef REHLDS_FIXES
+ bool bConDebug = true;
+#else
+ bool bConDebug = (sv_rcon_condebug.value > 0.0f);
+#endif
+
+ if (bConDebug)
{
- Con_Printf("Bad Rcon from %s:\n%s\n", NET_AdrToString(*net_from_), remaining);
- Log_Printf("Bad Rcon: \"%s\" from \"%s\"\n", remaining, NET_AdrToString(*net_from_));
- }
- else
- {
- Con_Printf("Rcon from %s:\n%s\n", NET_AdrToString(*net_from_), remaining);
- Log_Printf("Rcon: \"%s\" from \"%s\"\n", remaining, NET_AdrToString(*net_from_));
+ if (invalid)
+ {
+ Con_Printf("Bad Rcon from %s:\n%s\n", NET_AdrToString(*net_from_), remaining);
+ Log_Printf("Bad Rcon: \"%s\" from \"%s\"\n", remaining, NET_AdrToString(*net_from_));
+ }
+ else
+ {
+ Con_Printf("Rcon from %s:\n%s\n", NET_AdrToString(*net_from_), remaining);
+ Log_Printf("Rcon: \"%s\" from \"%s\"\n", remaining, NET_AdrToString(*net_from_));
+ }
}
SV_BeginRedirect(RD_PACKET, net_from_);
- if (invalid)
+ if (bConDebug && invalid)
{
if (invalid == 2)
Con_Printf("Bad rcon_password.\n");
@@ -3442,7 +3457,8 @@ void SV_Rcon(netadr_t *net_from_)
char *data = COM_Parse(COM_Parse(COM_Parse(remaining)));
if (!data)
{
- Con_Printf("Empty rcon\n");
+ if (bConDebug)
+ Con_Printf("Empty rcon\n");
#ifdef REHLDS_FIXES
//missing SV_EndRedirect()
@@ -7787,6 +7803,7 @@ void SV_Init(void)
Cvar_RegisterVariable(&sv_delayed_spray_upload);
Cvar_RegisterVariable(&sv_rehlds_force_dlmax);
Cvar_RegisterVariable(&sv_rehlds_hull_centering);
+ Cvar_RegisterVariable(&sv_rcon_condebug);
#endif
for (int i = 0; i < MAX_MODELS; i++)
diff --git a/rehlds/public/rehlds/rehlds_api.h b/rehlds/public/rehlds/rehlds_api.h
index 8ecbde2..7923650 100644
--- a/rehlds/public/rehlds/rehlds_api.h
+++ b/rehlds/public/rehlds/rehlds_api.h
@@ -174,8 +174,8 @@ typedef IVoidHookChain IRehldsHook_Cvar_DirectSet
typedef IVoidHookChainRegistry IRehldsHookRegistry_Cvar_DirectSet;
//SV_EstablishTimeBase hook
-typedef IVoidHookChain IRehldsHook_SV_EstablishTimeBase;
-typedef IVoidHookChainRegistry IRehldsHookRegistry_SV_EstablishTimeBase;
+typedef IVoidHookChain IRehldsHook_SV_EstablishTimeBase;
+typedef IVoidHookChainRegistry IRehldsHookRegistry_SV_EstablishTimeBase;
//SV_Spawn_f hook
typedef IVoidHookChain<> IRehldsHook_SV_Spawn_f;
@@ -185,6 +185,10 @@ typedef IVoidHookChainRegistry<> IRehldsHookRegistry_SV_Spawn_f;
typedef IHookChain IRehldsHook_SV_CreatePacketEntities;
typedef IHookChainRegistry IRehldsHookRegistry_SV_CreatePacketEntities;
+//SV_EmitSound2 hook
+typedef IHookChain IRehldsHook_SV_EmitSound2;
+typedef IHookChainRegistry IRehldsHookRegistry_SV_EmitSound2;
+
class IRehldsHookchains {
public:
virtual ~IRehldsHookchains() { }
@@ -226,6 +230,7 @@ public:
virtual IRehldsHookRegistry_SV_EstablishTimeBase* SV_EstablishTimeBase() = 0;
virtual IRehldsHookRegistry_SV_Spawn_f* SV_Spawn_f() = 0;
virtual IRehldsHookRegistry_SV_CreatePacketEntities* SV_CreatePacketEntities() = 0;
+ virtual IRehldsHookRegistry_SV_EmitSound2* SV_EmitSound2() = 0;
};
struct RehldsFuncs_t {
@@ -273,6 +278,8 @@ struct RehldsFuncs_t {
qboolean(*SV_FileInConsistencyList)(const char *filename, struct consistency_s **ppconsist);
qboolean(*Steam_NotifyClientConnect)(IGameClient *cl, const void *pvSteam2Key, unsigned int ucbSteam2Key);
void(*Steam_NotifyClientDisconnect)(IGameClient* cl);
+ void(*SV_StartSound)(int recipients, edict_t *entity, int channel, const char *sample, int volume, float attenuation, int flags, int pitch);
+ bool(*SV_EmitSound2)(edict_t *entity, IGameClient *receiver, int channel, const char *sample, float volume, float attenuation, int flags, int pitch, int emitFlags, const float *pOrigin);
};
class IRehldsApi {
diff --git a/rehlds/rehlds/rehlds_api_impl.cpp b/rehlds/rehlds/rehlds_api_impl.cpp
index f1e74a8..7fe9a7f 100644
--- a/rehlds/rehlds/rehlds_api_impl.cpp
+++ b/rehlds/rehlds/rehlds_api_impl.cpp
@@ -129,6 +129,10 @@ cvar_t* EXT_FUNC GetCvarVars_api() {
return cvar_vars;
}
+void EXT_FUNC SV_StartSound_api(int recipients, edict_t *entity, int channel, const char *sample, int volume, float attenuation, int flags, int pitch) {
+ SV_StartSound(recipients, entity, channel, sample, volume, attenuation, flags, pitch);
+}
+
void* EXT_FUNC Rehlds_GetPluginApi(const char *name) {
auto api = FindPluginApiByName(name);
return api ? api->impl : NULL;
@@ -194,9 +198,76 @@ RehldsFuncs_t g_RehldsApiFuncs =
&Rehlds_RegisterPluginApi,
&SV_FileInConsistencyList,
&Steam_NotifyClientConnect_api,
- &Steam_NotifyClientDisconnect_api
+ &Steam_NotifyClientDisconnect_api,
+ &SV_StartSound_api,
+ &SV_EmitSound2_api
};
+bool EXT_FUNC SV_EmitSound2_internal(edict_t *entity, IGameClient *pReceiver, int channel, const char *sample, float volume, float attenuation, int flags, int pitch, int emitFlags, const float *pOrigin)
+{
+ bool bSendPAS = (channel != CHAN_STATIC && !(flags & SND_FL_STOP) && !(emitFlags & SND_EMIT2_NOPAS));
+ vec3_t origin = {0, 0, 0};
+
+ if (entity && entity != g_psv.edicts)
+ {
+ for (int i = 0; i < 3; ++i)
+ origin[i] = (entity->v.maxs[i] + entity->v.mins[i]) * 0.5f + entity->v.origin[i];
+ }
+ // only worldspawn
+ else if (pOrigin != nullptr)
+ {
+ for (int i = 0; i < 3; ++i)
+ origin[i] = pOrigin[i];
+ }
+
+ // spawn sound of the entity for everyone clients
+ if (!pReceiver)
+ {
+ if (!SV_BuildSoundMsg(entity, channel, sample, (int)(volume * 255.0f), attenuation, flags, pitch, origin, &g_psv.multicast))
+ return false;
+
+ int msg_destination = MSG_FL_NONE;
+ if (emitFlags & SND_EMIT2_INVOKER) {
+ msg_destination = MSG_FL_ONE;
+ }
+
+ if (bSendPAS)
+ {
+ SV_Multicast(entity, origin, msg_destination | MSG_FL_PAS, FALSE);
+ }
+ else
+ {
+ SV_Multicast(entity, origin, msg_destination | MSG_FL_BROADCAST, TRUE);
+ }
+ return true;
+ }
+
+ sizebuf_t *pBuffer;
+ client_t *receiver = pReceiver->GetClient();
+
+ if (bSendPAS && receiver->edict != entity) // if the sound for myself, then do not check PAS.
+ {
+ int leafnum = SV_PointLeafnum(origin);
+ if (!SV_ValidClientMulticast(receiver, leafnum, MSG_FL_PAS))
+ return false;
+
+ pBuffer = &receiver->datagram;
+ }
+ else
+ {
+ // reliable
+ pBuffer = &receiver->netchan.message;
+ }
+
+ // send to one client
+ return SV_BuildSoundMsg(entity, channel, sample, (int)(volume * 255.0f), attenuation, flags, pitch, origin, pBuffer) != FALSE;
+}
+
+bool EXT_FUNC SV_EmitSound2_api(edict_t *entity, IGameClient *receiver, int channel, const char *sample, float volume, float attenuation, int flags, int pitch, int emitFlags, const float *pOrigin)
+{
+ return g_RehldsHookchains.m_SV_EmitSound2.callChain(SV_EmitSound2_internal, entity, receiver, channel, sample, volume, attenuation, flags, pitch, emitFlags, pOrigin);
+}
+
sizebuf_t* EXT_FUNC GetNetMessage_api()
{
return &net_message;
@@ -376,6 +447,10 @@ IRehldsHookRegistry_SV_CreatePacketEntities* CRehldsHookchains::SV_CreatePacketE
return &m_SV_CreatePacketEntities;
}
+IRehldsHookRegistry_SV_EmitSound2* CRehldsHookchains::SV_EmitSound2() {
+ return &m_SV_EmitSound2;
+}
+
int EXT_FUNC CRehldsApi::GetMajorVersion()
{
return REHLDS_API_VERSION_MAJOR;
diff --git a/rehlds/rehlds/rehlds_api_impl.h b/rehlds/rehlds/rehlds_api_impl.h
index 246a4f0..e0ad877 100644
--- a/rehlds/rehlds/rehlds_api_impl.h
+++ b/rehlds/rehlds/rehlds_api_impl.h
@@ -179,6 +179,10 @@ typedef IVoidHookChainRegistryImpl<> CRehldsHookRegistry_SV_Spawn_f;
typedef IHookChainImpl CRehldsHook_SV_CreatePacketEntities;
typedef IHookChainRegistryImpl CRehldsHookRegistry_SV_CreatePacketEntities;
+//SV_EmitSound2 hook
+typedef IHookChainImpl CRehldsHook_SV_EmitSound2;
+typedef IHookChainRegistryImpl CRehldsHookRegistry_SV_EmitSound2;
+
class CRehldsHookchains : public IRehldsHookchains {
public:
CRehldsHookRegistry_Steam_NotifyClientConnect m_Steam_NotifyClientConnect;
@@ -218,6 +222,7 @@ public:
CRehldsHookRegistry_SV_EstablishTimeBase m_SV_EstablishTimeBase;
CRehldsHookRegistry_SV_Spawn_f m_SV_Spawn_f;
CRehldsHookRegistry_SV_CreatePacketEntities m_SV_CreatePacketEntities;
+ CRehldsHookRegistry_SV_EmitSound2 m_SV_EmitSound2;
public:
virtual IRehldsHookRegistry_Steam_NotifyClientConnect* Steam_NotifyClientConnect();
@@ -257,6 +262,7 @@ public:
virtual IRehldsHookRegistry_SV_EstablishTimeBase* SV_EstablishTimeBase();
virtual IRehldsHookRegistry_SV_Spawn_f* SV_Spawn_f();
virtual IRehldsHookRegistry_SV_CreatePacketEntities* SV_CreatePacketEntities();
+ virtual IRehldsHookRegistry_SV_EmitSound2* SV_EmitSound2();
};
extern CRehldsHookchains g_RehldsHookchains;
@@ -278,4 +284,6 @@ public:
extern sizebuf_t* GetNetMessage_api();
extern IGameClient* GetHostClient_api();
-extern int* GetMsgReadCount_api();
\ No newline at end of file
+extern int* GetMsgReadCount_api();
+
+bool SV_EmitSound2_api(edict_t *entity, IGameClient *receiver, int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch, int emitFlags, const float *pOrigin);