mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
* Move member vars to correct place, to match it with the engine. * Added out-of-band network message ID's for the R5 engine. Also implemented 'ServerDataBlockSender::SendDataBlock()' and 'ClientDataBlockReceiver::AcknowledgeTransmission()'. NOTE that these are currently not tested, and also not in use! The code uses the version stored in the vftable which is what the engine itself provides. These have been implemented for reference only. If they need to be used, they need to be thoroughly tested first!
149 lines
4.5 KiB
C++
149 lines
4.5 KiB
C++
//===========================================================================//
|
|
//
|
|
// Purpose: server side data block sender
|
|
//
|
|
//===========================================================================//
|
|
#include "engine/client/client.h"
|
|
#include "common/proto_oob.h"
|
|
#include "datablock_sender.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: sends the data block
|
|
//-----------------------------------------------------------------------------
|
|
void ServerDataBlockSender::SendDataBlock(const short transferId, const int transferSize,
|
|
const short transferNr, const short blockNr, const uint8_t* const blockData, const int blockSize)
|
|
{
|
|
const CClient* const cl = m_pClient;
|
|
|
|
if (!cl)
|
|
{
|
|
Assert(0, "ServerDataBlockSender::SendDataBlock() called without a valid client handle!");
|
|
return;
|
|
}
|
|
|
|
const CNetChan* const chan = cl->m_NetChannel;
|
|
|
|
if (!chan)
|
|
{
|
|
Assert(0, "ServerDataBlockSender::SendDataBlock() called without a valid net channel!");
|
|
return;
|
|
}
|
|
|
|
char dataBuf[DATABLOCK_FRAGMENT_PACKET_SIZE];
|
|
bf_write buf(&dataBuf, sizeof(dataBuf));
|
|
|
|
// msg data (gets processed on client's out of band packet handler)
|
|
buf.WriteLong(CONNECTIONLESS_HEADER);
|
|
buf.WriteByte(S2C_DATABLOCK_FRAGMENT);
|
|
|
|
// transfer info
|
|
buf.WriteByte(transferId);
|
|
buf.WriteLong(transferSize);
|
|
buf.WriteByte(transferNr);
|
|
|
|
// block info
|
|
buf.WriteByte(blockNr);
|
|
buf.WriteLong(blockSize);
|
|
|
|
// block data
|
|
buf.WriteBytes(blockData, blockSize);
|
|
|
|
// send the data block packet
|
|
v_NET_SendPacket(NULL,
|
|
chan->GetSocket(),
|
|
chan->GetRemoteAddress(),
|
|
buf.GetData(),
|
|
buf.GetNumBytesWritten(),
|
|
NULL, false, NULL, true);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: gets the resend rate
|
|
//-----------------------------------------------------------------------------
|
|
float ServerDataBlockSender::GetResendRate() const
|
|
{
|
|
const CClient* const pClient = m_pClient;
|
|
|
|
if (!pClient)
|
|
return 0.0f;
|
|
|
|
const CNetChan* const pChan = pClient->GetNetChan();
|
|
|
|
if (!pChan)
|
|
return 0.0f;
|
|
|
|
if (m_bStartedTransfer)
|
|
return 0.0f;
|
|
|
|
const float netResendRate = pChan->GetResendRate();
|
|
|
|
if (netResendRate < net_datablock_networkLossForSlowSpeed->GetFloat())
|
|
{
|
|
return m_flResendRate;
|
|
}
|
|
|
|
return netResendRate;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: gets the receiver name (client name as registered on the server)
|
|
//-----------------------------------------------------------------------------
|
|
const char* ServerDataBlockSender::GetReceiverName() const
|
|
{
|
|
return m_pClient->m_szServerName;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: write the whole data in the data block scratch buffer
|
|
//-----------------------------------------------------------------------------
|
|
void ServerDataBlockSender::WriteDataBlock(const uint8_t* const sourceData, const int dataSize,
|
|
const bool isMultiplayer, const char* const debugName)
|
|
{
|
|
AcquireSRWLockExclusive(&m_Lock);
|
|
|
|
ServerDataBlockHeader_s* const pHeader = reinterpret_cast<ServerDataBlockHeader_s*>(m_pScratchBuffer);
|
|
bool copyRaw = true;
|
|
|
|
int actualDataSize = dataSize;
|
|
|
|
if (net_compressDataBlock->GetBool())
|
|
{
|
|
const int encodedSize = LZ4_compress_fast((const char*)sourceData, (char*)m_pScratchBuffer + sizeof(ServerDataBlockHeader_s),
|
|
dataSize, SNAPSHOT_SCRATCH_BUFFER_SIZE, net_compressDataBlockLzAcceleration->GetInt());
|
|
|
|
// this shouldn't happen at all
|
|
if (!encodedSize)
|
|
{
|
|
Assert(0);
|
|
Error(eDLL_T::SERVER, 0, "LZ4 error compressing data block for client.\n");
|
|
}
|
|
|
|
// make sure the encoded data is smaller than the raw data, in some cases
|
|
// this might turn larger which means we should just send raw data
|
|
else if (encodedSize < dataSize)
|
|
{
|
|
actualDataSize = encodedSize;
|
|
|
|
pHeader->isCompressed = true;
|
|
copyRaw = false;
|
|
}
|
|
}
|
|
|
|
// in case no compression was performed, we send the raw data
|
|
if (copyRaw)
|
|
{
|
|
// this should equal the dataSize at this point, even if compression failed
|
|
Assert(actualDataSize == dataSize);
|
|
|
|
pHeader->isCompressed = false;
|
|
memcpy(m_pScratchBuffer + sizeof(ServerDataBlockHeader_s), sourceData, actualDataSize);
|
|
}
|
|
|
|
// NOTE: we copy data in the scratch buffer with an offset of
|
|
// sizeof(ServerDataBlockHeader_s), the header gets send up as well so we
|
|
// have to take this into account !!!
|
|
StartBlockSender(actualDataSize + sizeof(ServerDataBlockHeader_s), isMultiplayer, debugName);
|
|
|
|
ReleaseSRWLockExclusive(&m_Lock);
|
|
}
|