diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5c7d66acf..8547aa3e4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,6 +25,9 @@ jobs: buildTest: 'Test Fixes' steps: + - name: Configure + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + - name: Checkout uses: actions/checkout@v4 with: @@ -90,8 +93,9 @@ jobs: shell: "pwsh" - name: Import PFX and sign + if: github.event_name != 'pull_request' env: - KEY_PFX_PASS: ${{ secrets.KEY_PFX_PASS}} + KEY_PFX_PASS: ${{ secrets.KEY_PFX_PASS }} run: | $pfxBase64 = "${{ secrets.KEY_PFX_B64 }}" [IO.File]::WriteAllBytes("${{ github.workspace }}\signing-cert.pfx", [Convert]::FromBase64String($pfxBase64)) @@ -158,11 +162,6 @@ jobs: container: debian:11-slim steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Install dependencies run: | dpkg --add-architecture i386 @@ -174,6 +173,14 @@ jobs: git cmake rsync \ g++ gcc + - name: Configure + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: GPG Import run: | echo "${{ secrets.PUB_ASC }}" > "${{ secrets.PUB_ASC_FILE }}" diff --git a/README.md b/README.md index 3ca47c715..7533e4b43 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,7 @@ sudo apt-get update sudo apt-get install -y gcc-multilib g++-multilib sudo apt-get install -y build-essential sudo apt-get install -y libc6-dev libc6-dev-i386 +sudo apt-get install -y cmake diff --git a/rehlds/common/const.h b/rehlds/common/const.h index 721a8dab2..f498db153 100644 --- a/rehlds/common/const.h +++ b/rehlds/common/const.h @@ -74,6 +74,7 @@ // 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 +#define SND_EMIT2_USE_ORIGIN (1<<2) // use given origin instead of entity origin // Engine edict->spawnflags #define SF_NOTINDEATHMATCH 0x0800 // Do not spawn when deathmatch and loading entities from a file diff --git a/rehlds/engine/info.cpp b/rehlds/engine/info.cpp index 6680d3571..d0a36e331 100644 --- a/rehlds/engine/info.cpp +++ b/rehlds/engine/info.cpp @@ -856,6 +856,12 @@ qboolean Info_IsValid(const char *s) return false; }; + // invalid utf8 chars are deprecated + if (!Q_UnicodeValidate(s)) + { + return FALSE; + } + while (*s == '\\') { const char* key = ++s; diff --git a/rehlds/engine/sv_main.cpp b/rehlds/engine/sv_main.cpp index 20ba978ff..6b70b8835 100644 --- a/rehlds/engine/sv_main.cpp +++ b/rehlds/engine/sv_main.cpp @@ -5781,8 +5781,12 @@ void SV_PropagateCustomizations(void) pResource = &pCust->resource; #ifdef REHLDS_FIXES + // skip logos if sv_send_logos is 0 if ((pResource->ucFlags & RES_CUSTOM) && !sv_send_logos.value) + { + pCust = pCust->pNext; continue; + } #endif MSG_WriteByte(&host_client->netchan.message, svc_customization); diff --git a/rehlds/rehlds/rehlds_api_impl.cpp b/rehlds/rehlds/rehlds_api_impl.cpp index e4f0e00bc..9cdd7e196 100644 --- a/rehlds/rehlds/rehlds_api_impl.cpp +++ b/rehlds/rehlds/rehlds_api_impl.cpp @@ -579,7 +579,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)); 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) origin[i] = (entity->v.maxs[i] + entity->v.mins[i]) * 0.5f + entity->v.origin[i]; diff --git a/rehlds/rehlds/rehlds_messagemngr_impl.cpp b/rehlds/rehlds/rehlds_messagemngr_impl.cpp index 534051932..6179504b3 100644 --- a/rehlds/rehlds/rehlds_messagemngr_impl.cpp +++ b/rehlds/rehlds/rehlds_messagemngr_impl.cpp @@ -213,13 +213,13 @@ class MessageImpl: public IMessage void setCopybackBuffer(sizebuf_t *pbuf); // 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 void clear(); template - 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 void setTxformBuffer(size_t index, size_t startPos, size_t oldLength, size_t newLength); @@ -263,6 +263,7 @@ class MessageImpl: public IMessage 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 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) @@ -369,17 +370,31 @@ static size_t SIZEOF_PARAMTYPE[] = }; // 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 ¶m = m_params[m_paramCount++]; - param.type = type; - param.newlen = param.oldlen = (length == -1) ? SIZEOF_PARAMTYPE[static_cast(type)] : length; - param.posBack = param.posFront = gMsgBuffer.cursize; + param.type = type; + param.newlen = param.oldlen = (length == -1) ? SIZEOF_PARAMTYPE[static_cast(type)] : length; + param.posBack = param.posFront = gMsgBuffer.cursize; + param.sign[BACK] = param.sign[FRONT] = sign; +} + +template +inline void setValue(void *pbuf, T value) +{ + *static_cast(pbuf) = value; +} + +template +inline int getValueInt(const void *pbuf, bool sign = false) +{ + return sign ? + *static_cast(pbuf) : *static_cast *>(pbuf); } // Sets the value of a primitive parameter at the given index template -void MessageImpl::setParamPrimitive(size_t index, T value) +void MessageImpl::setParamPrimitive(size_t index, T value, bool sign) { // Ensure index is within bounds if (index >= m_paramCount) @@ -392,30 +407,32 @@ void MessageImpl::setParamPrimitive(size_t index, T value) switch (param.type) { case IMessage::ParamType::Byte: - *(uint8 *)pbuf = value; + setValue(pbuf, value); break; case IMessage::ParamType::Char: - *(int8 *)pbuf = value; + setValue(pbuf, value); break; case IMessage::ParamType::Short: case IMessage::ParamType::Entity: - *(int16 *)pbuf = value; + setValue(pbuf, value); break; case IMessage::ParamType::Long: - *(uint32 *)pbuf = value; + setValue(pbuf, value); break; case IMessage::ParamType::Angle: // Convert angle value to byte representation with loss of precision - *(uint8 *)pbuf = (int64)(fmod((double)value, 360.0) * 256.0 / 360.0) & 0xff; + setValue(pbuf, (int64)(fmod((double)value, 360.0) * 256.0 / 360.0) & 0xff); break; case IMessage::ParamType::Coord: // Convert coordinate value to short integer representation with loss of precision - *(int16 *)pbuf = (int16)(int)(value * 8.0); + setValue(pbuf, (int)(value * 8.0)); break; default: return; // bad type } + param.sign[BACK] = sign; + // Mark message as modified param.modified = true; @@ -469,14 +486,14 @@ int MessageImpl::getParamInt(size_t index) const switch (param.type) { case IMessage::ParamType::Byte: - return *(uint8 *)buf; + return getValueInt(buf); case IMessage::ParamType::Char: - return *(int8 *)buf; + return getValueInt(buf, param.sign[BACK]); case IMessage::ParamType::Short: case IMessage::ParamType::Entity: - return *(int16 *)buf; + return getValueInt(buf, param.sign[BACK]); case IMessage::ParamType::Long: - return *(uint32 *)buf; + return getValueInt(buf); default: return 0; // bad type } @@ -495,9 +512,9 @@ float MessageImpl::getParamFloat(size_t index) const switch (param.type) { case IMessage::ParamType::Angle: - return (float)(*(uint8 *)buf * (360.0 / 256.0)); + return (float)((uint8)getValueInt(buf) * (360.0 / 256.0)); case IMessage::ParamType::Coord: - return (float)(*(int16 *)buf * (1.0 / 8)); + return (float)((int16)getValueInt(buf) * (1.0 / 8)); default: break; // bad type } @@ -532,14 +549,14 @@ int MessageImpl::getOriginalParamInt(size_t index) const switch (param.type) { case IMessage::ParamType::Byte: - return *(uint8 *)buf; + return getValueInt(buf); case IMessage::ParamType::Char: - return *(int8 *)buf; + return getValueInt(buf, param.sign[FRONT]); case IMessage::ParamType::Short: case IMessage::ParamType::Entity: - return *(int16 *)buf; + return getValueInt(buf, param.sign[FRONT]); case IMessage::ParamType::Long: - return *(uint32 *)buf; + return getValueInt(buf); default: return 0; // bad type } @@ -557,9 +574,9 @@ float MessageImpl::getOriginalParamFloat(size_t index) const switch (param.type) { case IMessage::ParamType::Angle: - return (float)(*(uint8 *)buf * (360.0 / 256.0)); + return (float)((uint8)getValueInt(buf) * (360.0 / 256.0)); case IMessage::ParamType::Coord: - return (float)(*(int16 *)buf * (1.0 / 8)); + return (float)((int16)getValueInt(buf) * (1.0 / 8)); default: 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 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 @@ -710,23 +727,23 @@ void MessageImpl::resetParam(size_t index) switch (param.type) { case IMessage::ParamType::Byte: - *(uint8 *)pbackbuf = *(uint8 *)pfrontbuf; + setValue(pbackbuf, getValueInt(pfrontbuf)); break; case IMessage::ParamType::Char: - *(int8 *)pbackbuf = *(int8 *)pfrontbuf; + setValue(pbackbuf, getValueInt(pfrontbuf)); break; case IMessage::ParamType::Short: case IMessage::ParamType::Entity: - *(int16 *)pbackbuf = *(int16 *)pfrontbuf; + setValue(pbackbuf, getValueInt(pfrontbuf)); break; case IMessage::ParamType::Long: - *(uint32 *)pbackbuf = *(uint32 *)pfrontbuf; + setValue(pbackbuf, getValueInt(pfrontbuf)); break; case IMessage::ParamType::Angle: - *(uint8 *)pbackbuf = *(uint8 *)pfrontbuf; + setValue(pbackbuf, getValueInt(pfrontbuf)); break; case IMessage::ParamType::Coord: - *(int16 *)pbackbuf = *(int16 *)pfrontbuf; + setValue(pbackbuf, getValueInt(pfrontbuf)); break; case IMessage::ParamType::String: // Return the original string value from the front buffer @@ -740,6 +757,8 @@ void MessageImpl::resetParam(size_t index) // Unmark message as modified param.modified = false; + + param.sign[BACK] = param.sign[FRONT]; } // Resets a specific message parameter to its original value @@ -955,7 +974,7 @@ bool MessageManagerImpl::MessageEnd() 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 if (m_inblock) @@ -966,7 +985,7 @@ bool MessageManagerImpl::WriteParam(IMessage::ParamType type, size_t length) { // Add parameter to top stack message MessageImpl &msg = m_stack.top(); - msg.addParam(type, length); + msg.addParam(type, sign, length); } return true; @@ -1002,13 +1021,13 @@ void EXT_FUNC PF_WriteByte_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); } 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); } @@ -1032,13 +1051,13 @@ void EXT_FUNC PF_WriteCoord_Intercept(float flValue) 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); } 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); } diff --git a/rehlds/rehlds/rehlds_messagemngr_impl.h b/rehlds/rehlds/rehlds_messagemngr_impl.h index f016b193e..dbb96367e 100644 --- a/rehlds/rehlds/rehlds_messagemngr_impl.h +++ b/rehlds/rehlds/rehlds_messagemngr_impl.h @@ -93,7 +93,7 @@ class MessageManagerImpl: public IMessageManager bool MessageEnd(); 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_inhook; // Flag indicating whether a message hook is currently active