2
0
mirror of https://github.com/rehlds/rehlds.git synced 2025-04-09 11:00:08 +03:00

Compare commits

...

8 Commits

10 changed files with 99 additions and 43 deletions

View File

@ -222,6 +222,7 @@ jobs:
#export for global use #export for global use
echo "GPG_LINUX_FINGERPRINT=$GPG_LINUX_FINGERPRINT" >> $GITHUB_ENV echo "GPG_LINUX_FINGERPRINT=$GPG_LINUX_FINGERPRINT" >> $GITHUB_ENV
shell: bash shell: bash
if: github.event_name != 'pull_request'
- name: Build and Run unittests - name: Build and Run unittests
run: | run: |

View File

@ -147,6 +147,7 @@ sudo apt-get update
sudo apt-get install -y gcc-multilib g++-multilib sudo apt-get install -y gcc-multilib g++-multilib
sudo apt-get install -y build-essential sudo apt-get install -y build-essential
sudo apt-get install -y libc6-dev libc6-dev-i386 sudo apt-get install -y libc6-dev libc6-dev-i386
sudo apt-get install -y cmake
</pre> </pre>
</li> </li>

View File

@ -74,6 +74,7 @@
// SV_EmitSound2 flags // SV_EmitSound2 flags
#define SND_EMIT2_NOPAS (1<<0) // never to do check PAS #define SND_EMIT2_NOPAS (1<<0) // never to do check PAS
#define SND_EMIT2_INVOKER (1<<1) // do not send to the client invoker #define SND_EMIT2_INVOKER (1<<1) // do not send to the client invoker
#define SND_EMIT2_USE_ORIGIN (1<<2) // use given origin instead of entity origin
// Engine edict->spawnflags // Engine edict->spawnflags
#define SF_NOTINDEATHMATCH 0x0800 // Do not spawn when deathmatch and loading entities from a file #define SF_NOTINDEATHMATCH 0x0800 // Do not spawn when deathmatch and loading entities from a file

View File

@ -856,6 +856,12 @@ qboolean Info_IsValid(const char *s)
return false; return false;
}; };
// invalid utf8 chars are deprecated
if (!Q_UnicodeValidate(s))
{
return FALSE;
}
while (*s == '\\') while (*s == '\\')
{ {
const char* key = ++s; const char* key = ++s;

View File

@ -5781,8 +5781,12 @@ void SV_PropagateCustomizations(void)
pResource = &pCust->resource; pResource = &pCust->resource;
#ifdef REHLDS_FIXES #ifdef REHLDS_FIXES
// skip logos if sv_send_logos is 0
if ((pResource->ucFlags & RES_CUSTOM) && !sv_send_logos.value) if ((pResource->ucFlags & RES_CUSTOM) && !sv_send_logos.value)
{
pCust = pCust->pNext;
continue; continue;
}
#endif #endif
MSG_WriteByte(&host_client->netchan.message, svc_customization); MSG_WriteByte(&host_client->netchan.message, svc_customization);

View File

@ -38,7 +38,7 @@
#include "pr_dlls.h" #include "pr_dlls.h"
#define REHLDS_API_VERSION_MAJOR 3 #define REHLDS_API_VERSION_MAJOR 3
#define REHLDS_API_VERSION_MINOR 14 #define REHLDS_API_VERSION_MINOR 15
//Steam_NotifyClientConnect hook //Steam_NotifyClientConnect hook
typedef IHookChain<qboolean, IGameClient*, const void*, unsigned int> IRehldsHook_Steam_NotifyClientConnect; typedef IHookChain<qboolean, IGameClient*, const void*, unsigned int> IRehldsHook_Steam_NotifyClientConnect;
@ -434,6 +434,9 @@ struct RehldsFuncs_t {
void(*MSG_BeginReading)(); void(*MSG_BeginReading)();
double(*GetHostFrameTime)(); double(*GetHostFrameTime)();
struct cmd_function_s *(*GetFirstCmdFunctionHandle)(); struct cmd_function_s *(*GetFirstCmdFunctionHandle)();
// Pause
void(*SetServerPause)(bool status);
}; };
class IRehldsApi { class IRehldsApi {

View File

@ -468,6 +468,26 @@ void EXT_FUNC SV_WriteMovevarsToClient_api(sizebuf_t *message)
SV_WriteMovevarsToClient(message, &sv_movevars); SV_WriteMovevarsToClient(message, &sv_movevars);
} }
void EXT_FUNC SetServerPause(bool setPause)
{
g_psv.paused = setPause;
#ifdef REHLDS_FIXES
for (int i = 0; i < g_psvs.maxclients; i++)
{
if (g_psvs.clients[i].fakeclient)
continue;
if (!g_psvs.clients[i].connected)
continue;
MSG_WriteByte(&g_psvs.clients[i].netchan.message, svc_setpause);
MSG_WriteByte(&g_psvs.clients[i].netchan.message, g_psv.paused);
}
#else // REHLDS_FIXES
MSG_WriteByte(&g_psv.reliable_datagram, svc_setpause);
MSG_WriteByte(&g_psv.reliable_datagram, g_psv.paused);
#endif // REHLDS_FIXES
}
CRehldsServerStatic g_RehldsServerStatic; CRehldsServerStatic g_RehldsServerStatic;
CRehldsServerData g_RehldsServerData; CRehldsServerData g_RehldsServerData;
CRehldsHookchains g_RehldsHookchains; CRehldsHookchains g_RehldsHookchains;
@ -571,7 +591,8 @@ RehldsFuncs_t g_RehldsApiFuncs =
&SZ_Clear_api, &SZ_Clear_api,
&MSG_BeginReading_api, &MSG_BeginReading_api,
&GetHostFrameTime_api, &GetHostFrameTime_api,
&GetFirstCmdFunctionHandle_api &GetFirstCmdFunctionHandle_api,
&SetServerPause,
}; };
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 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)
@ -579,7 +600,7 @@ bool EXT_FUNC SV_EmitSound2_internal(edict_t *entity, IGameClient *pReceiver, in
bool bSendPAS = (channel != CHAN_STATIC && !(flags & SND_FL_STOP) && !(emitFlags & SND_EMIT2_NOPAS)); bool bSendPAS = (channel != CHAN_STATIC && !(flags & SND_FL_STOP) && !(emitFlags & SND_EMIT2_NOPAS));
vec3_t origin = {0, 0, 0}; vec3_t origin = {0, 0, 0};
if (entity && entity != g_psv.edicts) if ((!pOrigin || !(emitFlags & SND_EMIT2_USE_ORIGIN)) && entity && entity != g_psv.edicts)
{ {
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
origin[i] = (entity->v.maxs[i] + entity->v.mins[i]) * 0.5f + entity->v.origin[i]; origin[i] = (entity->v.maxs[i] + entity->v.mins[i]) * 0.5f + entity->v.origin[i];

View File

@ -213,13 +213,13 @@ private:
void setCopybackBuffer(sizebuf_t *pbuf); void setCopybackBuffer(sizebuf_t *pbuf);
// Adds a parameter to the message // Adds a parameter to the message
void addParam(IMessage::ParamType type, size_t length); void addParam(IMessage::ParamType type, bool sign, size_t length);
// Clears the message after execution // Clears the message after execution
void clear(); void clear();
template <typename T> template <typename T>
void setParamPrimitive(size_t index, T value); void setParamPrimitive(size_t index, T value, bool sign = false);
// Transforms buffer after sets string for a parameter at the given index // Transforms buffer after sets string for a parameter at the given index
void setTxformBuffer(size_t index, size_t startPos, size_t oldLength, size_t newLength); void setTxformBuffer(size_t index, size_t startPos, size_t oldLength, size_t newLength);
@ -263,6 +263,7 @@ private:
size_t posFront : 9; // The stock position of the parameter in the buffer size_t posFront : 9; // The stock position of the parameter in the buffer
size_t oldlen : 9; // The length of the parameter in the buffer size_t oldlen : 9; // The length of the parameter in the buffer
size_t newlen : 9; // The length of the parameter in the buffer size_t newlen : 9; // The length of the parameter in the buffer
bool sign[MAX_STORAGE]; // Flag indicating that it has a signed value
}; };
#pragma pack(pop) #pragma pack(pop)
@ -369,17 +370,31 @@ static size_t SIZEOF_PARAMTYPE[] =
}; };
// Adds a parameter to the message // Adds a parameter to the message
void MessageImpl::addParam(IMessage::ParamType type, size_t length) void MessageImpl::addParam(IMessage::ParamType type, bool sign, size_t length)
{ {
Param_t &param = m_params[m_paramCount++]; Param_t &param = m_params[m_paramCount++];
param.type = type; param.type = type;
param.newlen = param.oldlen = (length == -1) ? SIZEOF_PARAMTYPE[static_cast<size_t>(type)] : length; param.newlen = param.oldlen = (length == -1) ? SIZEOF_PARAMTYPE[static_cast<size_t>(type)] : length;
param.posBack = param.posFront = gMsgBuffer.cursize; param.posBack = param.posFront = gMsgBuffer.cursize;
param.sign[BACK] = param.sign[FRONT] = sign;
}
template <typename T>
inline void setValue(void *pbuf, T value)
{
*static_cast<T *>(pbuf) = value;
}
template <typename T>
inline int getValueInt(const void *pbuf, bool sign = false)
{
return sign ?
*static_cast<const T *>(pbuf) : *static_cast<std::make_unsigned_t<const T> *>(pbuf);
} }
// Sets the value of a primitive parameter at the given index // Sets the value of a primitive parameter at the given index
template <typename T> template <typename T>
void MessageImpl::setParamPrimitive(size_t index, T value) void MessageImpl::setParamPrimitive(size_t index, T value, bool sign)
{ {
// Ensure index is within bounds // Ensure index is within bounds
if (index >= m_paramCount) if (index >= m_paramCount)
@ -392,30 +407,32 @@ void MessageImpl::setParamPrimitive(size_t index, T value)
switch (param.type) switch (param.type)
{ {
case IMessage::ParamType::Byte: case IMessage::ParamType::Byte:
*(uint8 *)pbuf = value; setValue<uint8>(pbuf, value);
break; break;
case IMessage::ParamType::Char: case IMessage::ParamType::Char:
*(int8 *)pbuf = value; setValue<int8>(pbuf, value);
break; break;
case IMessage::ParamType::Short: case IMessage::ParamType::Short:
case IMessage::ParamType::Entity: case IMessage::ParamType::Entity:
*(int16 *)pbuf = value; setValue<int16>(pbuf, value);
break; break;
case IMessage::ParamType::Long: case IMessage::ParamType::Long:
*(uint32 *)pbuf = value; setValue<uint32>(pbuf, value);
break; break;
case IMessage::ParamType::Angle: case IMessage::ParamType::Angle:
// Convert angle value to byte representation with loss of precision // Convert angle value to byte representation with loss of precision
*(uint8 *)pbuf = (int64)(fmod((double)value, 360.0) * 256.0 / 360.0) & 0xff; setValue<uint8>(pbuf, (int64)(fmod((double)value, 360.0) * 256.0 / 360.0) & 0xff);
break; break;
case IMessage::ParamType::Coord: case IMessage::ParamType::Coord:
// Convert coordinate value to short integer representation with loss of precision // Convert coordinate value to short integer representation with loss of precision
*(int16 *)pbuf = (int16)(int)(value * 8.0); setValue<int16>(pbuf, (int)(value * 8.0));
break; break;
default: default:
return; // bad type return; // bad type
} }
param.sign[BACK] = sign;
// Mark message as modified // Mark message as modified
param.modified = true; param.modified = true;
@ -469,14 +486,14 @@ int MessageImpl::getParamInt(size_t index) const
switch (param.type) switch (param.type)
{ {
case IMessage::ParamType::Byte: case IMessage::ParamType::Byte:
return *(uint8 *)buf; return getValueInt<uint8>(buf);
case IMessage::ParamType::Char: case IMessage::ParamType::Char:
return *(int8 *)buf; return getValueInt<int8>(buf, param.sign[BACK]);
case IMessage::ParamType::Short: case IMessage::ParamType::Short:
case IMessage::ParamType::Entity: case IMessage::ParamType::Entity:
return *(int16 *)buf; return getValueInt<int16>(buf, param.sign[BACK]);
case IMessage::ParamType::Long: case IMessage::ParamType::Long:
return *(uint32 *)buf; return getValueInt<uint32>(buf);
default: default:
return 0; // bad type return 0; // bad type
} }
@ -495,9 +512,9 @@ float MessageImpl::getParamFloat(size_t index) const
switch (param.type) switch (param.type)
{ {
case IMessage::ParamType::Angle: case IMessage::ParamType::Angle:
return (float)(*(uint8 *)buf * (360.0 / 256.0)); return (float)((uint8)getValueInt<uint8>(buf) * (360.0 / 256.0));
case IMessage::ParamType::Coord: case IMessage::ParamType::Coord:
return (float)(*(int16 *)buf * (1.0 / 8)); return (float)((int16)getValueInt<int16>(buf) * (1.0 / 8));
default: default:
break; // bad type break; // bad type
} }
@ -532,14 +549,14 @@ int MessageImpl::getOriginalParamInt(size_t index) const
switch (param.type) switch (param.type)
{ {
case IMessage::ParamType::Byte: case IMessage::ParamType::Byte:
return *(uint8 *)buf; return getValueInt<uint8>(buf);
case IMessage::ParamType::Char: case IMessage::ParamType::Char:
return *(int8 *)buf; return getValueInt<int8>(buf, param.sign[FRONT]);
case IMessage::ParamType::Short: case IMessage::ParamType::Short:
case IMessage::ParamType::Entity: case IMessage::ParamType::Entity:
return *(int16 *)buf; return getValueInt<int16>(buf, param.sign[FRONT]);
case IMessage::ParamType::Long: case IMessage::ParamType::Long:
return *(uint32 *)buf; return getValueInt<uint32>(buf);
default: default:
return 0; // bad type return 0; // bad type
} }
@ -557,9 +574,9 @@ float MessageImpl::getOriginalParamFloat(size_t index) const
switch (param.type) switch (param.type)
{ {
case IMessage::ParamType::Angle: case IMessage::ParamType::Angle:
return (float)(*(uint8 *)buf * (360.0 / 256.0)); return (float)((uint8)getValueInt<uint8>(buf) * (360.0 / 256.0));
case IMessage::ParamType::Coord: case IMessage::ParamType::Coord:
return (float)(*(int16 *)buf * (1.0 / 8)); return (float)((int16)getValueInt<int16>(buf) * (1.0 / 8));
default: default:
break; // bad type break; // bad type
} }
@ -584,7 +601,7 @@ const char *MessageImpl::getOriginalParamString(size_t index) const
// Sets the integer value of the parameter at the given index // Sets the integer value of the parameter at the given index
void MessageImpl::setParamInt(size_t index, int value) void MessageImpl::setParamInt(size_t index, int value)
{ {
setParamPrimitive(index, value); setParamPrimitive(index, value, value < 0);
} }
// Sets the float value of the parameter at the given index // Sets the float value of the parameter at the given index
@ -710,23 +727,23 @@ void MessageImpl::resetParam(size_t index)
switch (param.type) switch (param.type)
{ {
case IMessage::ParamType::Byte: case IMessage::ParamType::Byte:
*(uint8 *)pbackbuf = *(uint8 *)pfrontbuf; setValue<uint8>(pbackbuf, getValueInt<uint8>(pfrontbuf));
break; break;
case IMessage::ParamType::Char: case IMessage::ParamType::Char:
*(int8 *)pbackbuf = *(int8 *)pfrontbuf; setValue<int8>(pbackbuf, getValueInt<int8>(pfrontbuf));
break; break;
case IMessage::ParamType::Short: case IMessage::ParamType::Short:
case IMessage::ParamType::Entity: case IMessage::ParamType::Entity:
*(int16 *)pbackbuf = *(int16 *)pfrontbuf; setValue<int16>(pbackbuf, getValueInt<int16>(pfrontbuf));
break; break;
case IMessage::ParamType::Long: case IMessage::ParamType::Long:
*(uint32 *)pbackbuf = *(uint32 *)pfrontbuf; setValue<uint32>(pbackbuf, getValueInt<uint32>(pfrontbuf));
break; break;
case IMessage::ParamType::Angle: case IMessage::ParamType::Angle:
*(uint8 *)pbackbuf = *(uint8 *)pfrontbuf; setValue<uint8>(pbackbuf, getValueInt<uint8>(pfrontbuf));
break; break;
case IMessage::ParamType::Coord: case IMessage::ParamType::Coord:
*(int16 *)pbackbuf = *(int16 *)pfrontbuf; setValue<int16>(pbackbuf, getValueInt<int16>(pfrontbuf));
break; break;
case IMessage::ParamType::String: case IMessage::ParamType::String:
// Return the original string value from the front buffer // Return the original string value from the front buffer
@ -740,6 +757,8 @@ void MessageImpl::resetParam(size_t index)
// Unmark message as modified // Unmark message as modified
param.modified = false; param.modified = false;
param.sign[BACK] = param.sign[FRONT];
} }
// Resets a specific message parameter to its original value // Resets a specific message parameter to its original value
@ -955,7 +974,7 @@ bool MessageManagerImpl::MessageEnd()
return false; return false;
} }
bool MessageManagerImpl::WriteParam(IMessage::ParamType type, size_t length) bool MessageManagerImpl::WriteParam(IMessage::ParamType type, bool sign, size_t length)
{ {
// Check if in block mode // Check if in block mode
if (m_inblock) if (m_inblock)
@ -966,7 +985,7 @@ bool MessageManagerImpl::WriteParam(IMessage::ParamType type, size_t length)
{ {
// Add parameter to top stack message // Add parameter to top stack message
MessageImpl &msg = m_stack.top(); MessageImpl &msg = m_stack.top();
msg.addParam(type, length); msg.addParam(type, sign, length);
} }
return true; return true;
@ -1002,13 +1021,13 @@ void EXT_FUNC PF_WriteByte_Intercept(int iValue)
void EXT_FUNC PF_WriteChar_Intercept(int iValue) void EXT_FUNC PF_WriteChar_Intercept(int iValue)
{ {
if (MessageManager().WriteParam(IMessage::ParamType::Char)) if (MessageManager().WriteParam(IMessage::ParamType::Char, iValue < 0))
PF_WriteChar_I(iValue); PF_WriteChar_I(iValue);
} }
void EXT_FUNC PF_WriteShort_Intercept(int iValue) void EXT_FUNC PF_WriteShort_Intercept(int iValue)
{ {
if (MessageManager().WriteParam(IMessage::ParamType::Short)) if (MessageManager().WriteParam(IMessage::ParamType::Short, iValue < 0))
PF_WriteShort_I(iValue); PF_WriteShort_I(iValue);
} }
@ -1032,13 +1051,13 @@ void EXT_FUNC PF_WriteCoord_Intercept(float flValue)
void EXT_FUNC PF_WriteString_Intercept(const char *sz) void EXT_FUNC PF_WriteString_Intercept(const char *sz)
{ {
if (MessageManager().WriteParam(IMessage::ParamType::String, sz ? Q_strlen(sz) + 1 : 1)) if (MessageManager().WriteParam(IMessage::ParamType::String, false, sz ? Q_strlen(sz) + 1 : 1))
PF_WriteString_I(sz); PF_WriteString_I(sz);
} }
void EXT_FUNC PF_WriteEntity_Intercept(int iValue) void EXT_FUNC PF_WriteEntity_Intercept(int iValue)
{ {
if (MessageManager().WriteParam(IMessage::ParamType::Entity)) if (MessageManager().WriteParam(IMessage::ParamType::Entity, iValue < 0))
PF_WriteEntity_I(iValue); PF_WriteEntity_I(iValue);
} }

View File

@ -93,7 +93,7 @@ private:
bool MessageEnd(); bool MessageEnd();
private: private:
bool WriteParam(IMessage::ParamType type, size_t length = -1); bool WriteParam(IMessage::ParamType type, bool sign = false, size_t length = -1);
bool m_inblock; // Flag indicating whether a message block is currently active bool m_inblock; // Flag indicating whether a message block is currently active
bool m_inhook; // Flag indicating whether a message hook is currently active bool m_inhook; // Flag indicating whether a message hook is currently active

View File

@ -6,5 +6,5 @@
#pragma once #pragma once
#define VERSION_MAJOR 3 #define VERSION_MAJOR 3
#define VERSION_MINOR 14 #define VERSION_MINOR 15
#define VERSION_MAINTENANCE 0 #define VERSION_MAINTENANCE 0