Skip to content

Commit 4eed81d

Browse files
Synchronize changes from 1.6 master branch [ci skip]
cce4967 Add onPlayerResourceStart trigger check 63b91ff Improve internal buffer management for voice packets bd7f4c3 Clamp values in CWaterLevel::TestLineAgainstWater 6fd0825 Update installer en_US pot
2 parents 595f0bf + cce4967 commit 4eed81d

20 files changed

+282
-258
lines changed

Client/mods/deathmatch/CVoiceRecorder.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ void CVoiceRecorder::Init(bool bEnabled, unsigned int uiServerSampleRate, unsign
101101
if (iBitRate)
102102
speex_encoder_ctl(m_pSpeexEncoderState, SPEEX_SET_BITRATE, &iBitRate);
103103

104-
m_pOutgoingBuffer = (char*)malloc(m_uiBufferSizeBytes * FRAME_OUTGOING_BUFFER_COUNT);
104+
m_pOutgoingBuffer = (unsigned char*)malloc(m_uiBufferSizeBytes * FRAME_OUTGOING_BUFFER_COUNT);
105105
m_uiOutgoingReadIndex = 0;
106106
m_uiOutgoingWriteIndex = 0;
107107

@@ -247,9 +247,9 @@ void CVoiceRecorder::DoPulse()
247247
{
248248
std::lock_guard<std::mutex> lock(m_Mutex);
249249

250-
char* pInputBuffer;
251-
char bufTempOutput[2048];
252-
unsigned int uiTotalBufferSize = m_uiBufferSizeBytes * FRAME_OUTGOING_BUFFER_COUNT;
250+
unsigned char* pInputBuffer;
251+
unsigned char audioBuffer[2048]{};
252+
unsigned int uiTotalBufferSize = m_uiBufferSizeBytes * FRAME_OUTGOING_BUFFER_COUNT;
253253

254254
// Only send every 100 ms
255255
if (CClientTime::GetTime() - m_ulTimeOfLastSend > 100 && m_VoiceState != VOICESTATE_AWAITING_INPUT)
@@ -280,8 +280,8 @@ void CVoiceRecorder::DoPulse()
280280
{
281281
unsigned t;
282282
for (t = 0; t < uiSpeexBlockSize; t++)
283-
bufTempOutput[t] = m_pOutgoingBuffer[t % uiTotalBufferSize];
284-
pInputBuffer = bufTempOutput;
283+
audioBuffer[t] = m_pOutgoingBuffer[t % uiTotalBufferSize];
284+
pInputBuffer = audioBuffer;
285285
}
286286
else
287287
pInputBuffer = m_pOutgoingBuffer + m_uiOutgoingReadIndex;
@@ -296,9 +296,9 @@ void CVoiceRecorder::DoPulse()
296296

297297
m_bIsSendingVoiceData = true;
298298

299-
unsigned int uiBytesWritten = speex_bits_write(&speexBits, bufTempOutput, 2048);
299+
unsigned int audioBufferLength = speex_bits_write(&speexBits, reinterpret_cast<char*>(audioBuffer), 2048);
300300

301-
g_pClientGame->GetLocalPlayer()->GetVoice()->DecodeAndBuffer(bufTempOutput, uiBytesWritten);
301+
g_pClientGame->GetLocalPlayer()->GetVoice()->DecodeAndBuffer(audioBuffer, audioBufferLength);
302302

303303
NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream();
304304
if (pBitStream)
@@ -307,8 +307,8 @@ void CVoiceRecorder::DoPulse()
307307

308308
if (pLocalPlayer)
309309
{
310-
pBitStream->Write((unsigned short)uiBytesWritten); // size of buffer / voice data
311-
pBitStream->Write((char*)bufTempOutput, uiBytesWritten); // voice data
310+
pBitStream->Write((unsigned short)audioBufferLength);
311+
pBitStream->Write(reinterpret_cast<char*>(audioBuffer), audioBufferLength);
312312

313313
g_pNet->SendPacket(PACKET_ID_VOICE_DATA, pBitStream, PACKET_PRIORITY_LOW, PACKET_RELIABILITY_UNRELIABLE_SEQUENCED,
314314
PACKET_ORDERING_VOICE);

Client/mods/deathmatch/CVoiceRecorder.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,11 @@ class CVoiceRecorder
7979
void* m_pSpeexEncoderState;
8080
SpeexPreprocessState* m_pSpeexPreprocState;
8181

82-
char* m_pOutgoingBuffer;
83-
int m_iSpeexOutgoingFrameSampleCount;
84-
unsigned int m_uiOutgoingReadIndex;
85-
unsigned int m_uiOutgoingWriteIndex;
86-
bool m_bIsSendingVoiceData;
82+
unsigned char* m_pOutgoingBuffer;
83+
int m_iSpeexOutgoingFrameSampleCount;
84+
unsigned int m_uiOutgoingReadIndex;
85+
unsigned int m_uiOutgoingWriteIndex;
86+
bool m_bIsSendingVoiceData;
8787

8888
unsigned long m_ulTimeOfLastSend;
8989

Client/mods/deathmatch/logic/CClientPlayerVoice.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,11 @@ void CClientPlayerVoice::DoPulse()
118118
}
119119
}
120120

121-
void CClientPlayerVoice::DecodeAndBuffer(char* pBuffer, unsigned int bytesWritten)
121+
void CClientPlayerVoice::DecodeAndBuffer(const unsigned char* voiceBuffer, unsigned int voiceBufferLength)
122122
{
123+
if (!voiceBuffer || !voiceBufferLength || voiceBufferLength > 2048)
124+
return;
125+
123126
m_Mutex.lock();
124127

125128
if (!m_bVoiceActive)
@@ -143,7 +146,7 @@ void CClientPlayerVoice::DecodeAndBuffer(char* pBuffer, unsigned int bytesWritte
143146
SpeexBits speexBits;
144147
speex_bits_init(&speexBits);
145148

146-
speex_bits_read_from(&speexBits, (char*)(pBuffer), bytesWritten);
149+
speex_bits_read_from(&speexBits, reinterpret_cast<const char*>(voiceBuffer), voiceBufferLength);
147150
speex_decode_int(m_pSpeexDecoderState, &speexBits, (spx_int16_t*)pTempBuffer);
148151

149152
speex_bits_destroy(&speexBits);

Client/mods/deathmatch/logic/CClientPlayerVoice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class CClientPlayerVoice
2828
ZERO_ON_NEW
2929
CClientPlayerVoice(CClientPlayer* pPlayer, CVoiceRecorder* pVoiceRecorder);
3030
~CClientPlayerVoice();
31-
void DecodeAndBuffer(char* pBuffer, unsigned int bytesWritten);
31+
void DecodeAndBuffer(const unsigned char* voiceBuffer, unsigned int voiceBufferLength);
3232
void DoPulse();
3333

3434
bool m_bVoiceActive;

Client/mods/deathmatch/logic/CPacketHandler.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5023,8 +5023,9 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
50235023
uiTotalSizeProcessed = 0;
50245024

50255025
/*
5026-
* unsigned char (1) - resource name size
5026+
* unsigned char (1) - resource name size
50275027
* unsigned char (x) - resource name
5028+
* unsigned int (4) - start counter
50285029
* unsigned short (2) - resource id
50295030
* unsigned short (2) - resource entity id
50305031
* unsigned short (2) - resource dynamic entity id
@@ -5079,6 +5080,10 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
50795080
return;
50805081
}
50815082

5083+
// Start counter
5084+
unsigned int startCounter{};
5085+
bitStream.Read(startCounter);
5086+
50825087
// Resource ID
50835088
unsigned short usResourceID;
50845089
bitStream.Read(usResourceID);
@@ -5122,6 +5127,7 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
51225127
{
51235128
pResource->SetRemainingNoClientCacheScripts(usNoClientCacheScriptCount);
51245129
pResource->SetDownloadPriorityGroup(iDownloadPriorityGroup);
5130+
pResource->SetStartCounter(startCounter);
51255131

51265132
// Resource Chunk Type (F = Resource File, E = Exported Function)
51275133
unsigned char ucChunkType;
@@ -5403,24 +5409,26 @@ void CPacketHandler::Packet_DestroySatchels(NetBitStreamInterface& bitStream)
54035409

54045410
void CPacketHandler::Packet_VoiceData(NetBitStreamInterface& bitStream)
54055411
{
5406-
unsigned short usPacketSize;
5412+
unsigned short voiceBufferLength;
54075413
ElementID PlayerID;
5414+
54085415
if (bitStream.Read(PlayerID))
54095416
{
54105417
CClientPlayer* pPlayer = g_pClientGame->m_pPlayerManager->Get(PlayerID);
5411-
if (pPlayer && bitStream.Read(usPacketSize))
5418+
5419+
if (pPlayer && bitStream.Read(voiceBufferLength) && voiceBufferLength <= 2048)
54125420
{
5413-
char* pBuf = new char[usPacketSize];
5421+
const auto voiceBuffer = new unsigned char[voiceBufferLength];
54145422

5415-
if (bitStream.Read(pBuf, usPacketSize))
5423+
if (bitStream.Read(reinterpret_cast<char*>(voiceBuffer), voiceBufferLength))
54165424
{
54175425
if (pPlayer->GetVoice())
54185426
{
5419-
pPlayer->GetVoice()->DecodeAndBuffer(pBuf, usPacketSize);
5427+
pPlayer->GetVoice()->DecodeAndBuffer(voiceBuffer, voiceBufferLength);
54205428
}
54215429
}
54225430

5423-
delete[] pBuf;
5431+
delete[] voiceBuffer;
54245432
}
54255433
}
54265434
}

Client/mods/deathmatch/logic/CResource.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ void CResource::Load()
341341
{
342342
// Write resource net ID
343343
pBitStream->Write(GetNetID());
344+
pBitStream->Write(GetStartCounter());
344345
g_pNet->SendPacket(PACKET_ID_PLAYER_RESOURCE_START, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED);
345346
g_pNet->DeallocateNetBitStream(pBitStream);
346347
}

Client/mods/deathmatch/logic/CResource.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,13 @@ class CResource
110110
int GetDownloadPriorityGroup() { return m_iDownloadPriorityGroup; }
111111
void SetDownloadPriorityGroup(int iDownloadPriorityGroup) { m_iDownloadPriorityGroup = iDownloadPriorityGroup; }
112112

113+
void SetStartCounter(unsigned int startCounter) { m_startCounter = startCounter; }
114+
unsigned int GetStartCounter() const noexcept { return m_startCounter; }
115+
113116
private:
114117
unsigned short m_usNetID;
115118
uint m_uiScriptID;
119+
unsigned int m_startCounter{};
116120
SString m_strResourceName;
117121
CLuaMain* m_pLuaVM;
118122
CLuaManager* m_pLuaManager;

Client/multiplayer_sa/CMultiplayerSA_Weapons.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,47 @@ static void __declspec(naked) HOOK_CVisibilityPlugins_RenderWeaponPedsForPC()
235235
}
236236
}
237237

238+
//////////////////////////////////////////////////////////////////////////////////////////
239+
//
240+
// CWaterLevel::TestLineAgainstWater
241+
//
242+
// Limit the values to world bounds, because the water level does not exceed it.
243+
//
244+
//////////////////////////////////////////////////////////////////////////////////////////
245+
static void CLAMP_CWaterLevel_TestLineAgainstWater(float values[6])
246+
{
247+
for (int i = 0; i < 6; ++i)
248+
values[i] = Clamp(-3000.0f, values[i], 3000.0f);
249+
}
250+
251+
#define HOOKPOS_CWaterLevel_TestLineAgainstWater 0x6E61B0
252+
#define HOOKSIZE_CWaterLevel_TestLineAgainstWater 10
253+
static constexpr DWORD CONTINUE_CWaterLevel_TestLineAgainstWater = 0x6E61BA;
254+
static void _declspec(naked) HOOK_CWaterLevel_TestLineAgainstWater()
255+
{
256+
MTA_VERIFY_HOOK_LOCAL_SIZE;
257+
258+
__asm
259+
{
260+
// [esp+4] from.x
261+
// [esp+8] from.y
262+
// [esp+12] from.z
263+
// [esp+16] to.x
264+
// [esp+20] to.y
265+
// [esp+24] to.z
266+
pushad
267+
lea eax, [esp+32+4]
268+
push eax
269+
call CLAMP_CWaterLevel_TestLineAgainstWater
270+
add esp, 4
271+
popad
272+
273+
fld [esp+0Ch]
274+
sub esp, 88h
275+
jmp CONTINUE_CWaterLevel_TestLineAgainstWater
276+
}
277+
}
278+
238279
//////////////////////////////////////////////////////////////////////////////////////////
239280
//
240281
// CMultiplayerSA::InitHooks_Weapons
@@ -248,4 +289,5 @@ void CMultiplayerSA::InitHooks_Weapons()
248289
EZHookInstall(CShotInfo_Update);
249290
EZHookInstall(Fx_AddBulletImpact);
250291
EZHookInstall(CVisibilityPlugins_RenderWeaponPedsForPC);
292+
EZHookInstall(CWaterLevel_TestLineAgainstWater);
251293
}

Server/mods/deathmatch/logic/CGame.cpp

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,9 @@ void CGame::QuitPlayer(CPlayer& Player, CClient::eQuitReasons Reason, bool bSayI
15551555

15561556
Player.CallEvent("onPlayerQuit", Arguments);
15571557

1558+
// Tell the resource manager
1559+
m_pResourceManager->OnPlayerQuit(Player);
1560+
15581561
// Tell the map manager
15591562
m_pMapManager->OnPlayerQuit(Player);
15601563

@@ -3859,9 +3862,7 @@ void CGame::Packet_Voice_Data(CVoiceDataPacket& Packet)
38593862

38603863
if (m_pMainConfig->IsVoiceEnabled()) // Shouldn't really be receiving voice packets at all if voice is disabled
38613864
{
3862-
usDataLength = Packet.GetDataLength();
3863-
3864-
if (usDataLength > 0)
3865+
if (!Packet.IsEmpty())
38653866
{
38663867
CPlayer* pPlayer = Packet.GetSourcePlayer();
38673868

@@ -3890,9 +3891,6 @@ void CGame::Packet_Voice_Data(CVoiceDataPacket& Packet)
38903891
if (pPlayer->GetVoiceState() ==
38913892
VOICESTATE_TRANSMITTING) // If we reach here, and we're still in idle state, then the event was cancelled
38923893
{
3893-
const unsigned char* pBuffer = Packet.GetData();
3894-
CVoiceDataPacket VoicePacket(pPlayer, pBuffer, usDataLength);
3895-
38963894
// Make list of players to send the voice packet to
38973895
std::set<CPlayer*> playerSendMap;
38983896

@@ -3935,7 +3933,7 @@ void CGame::Packet_Voice_Data(CVoiceDataPacket& Packet)
39353933
}
39363934

39373935
// Send to all players in the send list
3938-
CPlayerManager::Broadcast(VoicePacket, playerSendMap);
3936+
CPlayerManager::Broadcast(Packet, playerSendMap);
39393937
}
39403938
}
39413939
}
@@ -4177,17 +4175,16 @@ void CGame::Packet_PlayerNetworkStatus(CPlayerNetworkStatusPacket& Packet)
41774175

41784176
void CGame::Packet_PlayerResourceStart(CPlayerResourceStartPacket& Packet)
41794177
{
4180-
CPlayer* pPlayer = Packet.GetSourcePlayer();
4181-
if (pPlayer)
4182-
{
4183-
CResource* pResource = Packet.GetResource();
4184-
if (pResource)
4185-
{
4186-
CLuaArguments Arguments;
4187-
Arguments.PushResource(pResource);
4188-
pPlayer->CallEvent("onPlayerResourceStart", Arguments, NULL);
4189-
}
4190-
}
4178+
CPlayer* sourcePlayer = Packet.GetSourcePlayer();
4179+
CResource* resource = Packet.GetResource();
4180+
unsigned int playerStartCounter = Packet.GetStartCounter();
4181+
4182+
if (!sourcePlayer || !resource || !resource->CanPlayerTriggerResourceStart(sourcePlayer, playerStartCounter))
4183+
return;
4184+
4185+
CLuaArguments Arguments;
4186+
Arguments.PushResource(resource);
4187+
sourcePlayer->CallEvent("onPlayerResourceStart", Arguments, nullptr);
41914188
}
41924189

41934190
void CGame::Packet_PlayerWorldSpecialProperty(CPlayerWorldSpecialPropertyPacket& packet) noexcept

Server/mods/deathmatch/logic/CResource.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,23 @@ void CResource::Reload()
362362
Load();
363363
}
364364

365+
bool CResource::CanPlayerTriggerResourceStart(CPlayer* player, unsigned int playerStartCounter)
366+
{
367+
if (playerStartCounter != m_startCounter || m_eState != EResourceState::Running)
368+
return false;
369+
370+
if (m_isRunningForPlayer.contains(player))
371+
return false;
372+
373+
m_isRunningForPlayer.insert(player);
374+
return true;
375+
}
376+
377+
void CResource::OnPlayerQuit(CPlayer& Player)
378+
{
379+
m_isRunningForPlayer.erase(&Player);
380+
}
381+
365382
CResource::~CResource()
366383
{
367384
CIdArray::PushUniqueId(this, EIdClass::RESOURCE, m_uiScriptID);
@@ -1017,6 +1034,7 @@ bool CResource::Start(std::list<CResource*>* pDependents, bool bManualStart, con
10171034
return false;
10181035
}
10191036

1037+
m_startCounter = std::max<unsigned int>(m_startCounter + 1, 1); // We consider zero to be an invalid start counter.
10201038
m_bStartedManually = bManualStart;
10211039

10221040
// Remember the client files state
@@ -1028,7 +1046,7 @@ bool CResource::Start(std::list<CResource*>* pDependents, bool bManualStart, con
10281046

10291047
// Broadcast new resourceelement that is loaded and tell the players that a new resource was started
10301048
g_pGame->GetMapManager()->BroadcastResourceElements(m_pResourceElement, m_pDefaultElementGroup);
1031-
g_pGame->GetPlayerManager()->BroadcastOnlyJoined(CResourceStartPacket(m_strResourceName.c_str(), this));
1049+
g_pGame->GetPlayerManager()->BroadcastOnlyJoined(CResourceStartPacket(m_strResourceName, this, m_startCounter));
10321050
SendNoClientCacheScripts();
10331051
m_bClientSync = true;
10341052

@@ -1174,6 +1192,9 @@ bool CResource::Stop(bool bManualStop)
11741192
// Broadcast the packet to joined players
11751193
g_pGame->GetPlayerManager()->BroadcastOnlyJoined(removePacket);
11761194

1195+
// Clear the list of players where this resource is running
1196+
std::exchange(m_isRunningForPlayer, {});
1197+
11771198
OnResourceStateChange("loaded");
11781199
m_eState = EResourceState::Loaded;
11791200
return true;
@@ -3312,8 +3333,7 @@ bool CResource::CheckState()
33123333

33133334
void CResource::OnPlayerJoin(CPlayer& Player)
33143335
{
3315-
// do the player join crap
3316-
Player.Send(CResourceStartPacket(m_strResourceName.c_str(), this));
3336+
Player.Send(CResourceStartPacket(m_strResourceName.c_str(), this, m_startCounter));
33173337
SendNoClientCacheScripts(&Player);
33183338
}
33193339

0 commit comments

Comments
 (0)