This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/engine/common/net_buffer.c

687 lines
15 KiB
C
Raw Normal View History

2011-05-09 22:00:00 +02:00
/*
net_buffer.c - network bitbuffer io functions
Copyright (C) 2010 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
2010-07-26 22:00:00 +02:00
#include "common.h"
2010-12-16 22:00:00 +01:00
#include "protocol.h"
2010-07-26 22:00:00 +02:00
#include "net_buffer.h"
2011-02-16 22:00:00 +01:00
#include "mathlib.h"
2010-07-26 22:00:00 +02:00
2017-02-07 22:00:00 +01:00
//#define DEBUG_NET_MESSAGES_SEND
//#define DEBUG_NET_MESSAGES_READ
2010-07-26 22:00:00 +02:00
// precalculated bit masks for WriteUBitLong.
// Using these tables instead of doing the calculations
// gives a 33% speedup in WriteUBitLong.
static dword BitWriteMasks[32][33];
static dword ExtraMasks[32];
2016-11-14 22:00:00 +01:00
short MSG_BigShort( short swap )
2010-11-21 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
return (swap >> 8)|(swap << 8);
2010-11-21 22:00:00 +01:00
}
2016-11-14 22:00:00 +01:00
void MSG_InitMasks( void )
2010-07-26 22:00:00 +02:00
{
uint startbit, endbit;
uint maskBit, nBitsLeft;
for( startbit = 0; startbit < 32; startbit++ )
{
for( nBitsLeft = 0; nBitsLeft < 33; nBitsLeft++ )
{
endbit = startbit + nBitsLeft;
2015-12-04 22:00:00 +01:00
BitWriteMasks[startbit][nBitsLeft] = (uint)BIT( startbit ) - 1;
if( endbit < 32 ) BitWriteMasks[startbit][nBitsLeft] |= ~((uint)BIT( endbit ) - 1 );
2010-07-26 22:00:00 +02:00
}
}
for( maskBit = 0; maskBit < 32; maskBit++ )
2015-12-04 22:00:00 +01:00
ExtraMasks[maskBit] = (uint)BIT( maskBit ) - 1;
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_InitExt( sizebuf_t *sb, const char *pDebugName, void *pData, int nBytes, int nMaxBits )
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
MSG_StartWriting( sb, pData, nBytes, 0, nMaxBits );
2018-03-08 22:00:00 +01:00
sb->pDebugName = pDebugName;
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, int nBits )
2010-07-26 22:00:00 +02:00
{
2010-08-04 22:00:00 +02:00
// make sure it's dword aligned and padded.
2010-08-05 22:00:00 +02:00
Assert(((dword)pData & 3 ) == 0 );
2010-07-26 22:00:00 +02:00
2018-03-08 22:00:00 +01:00
sb->pDebugName = "Unnamed";
2016-11-17 22:00:00 +01:00
sb->pData = (byte *)pData;
2010-07-26 22:00:00 +02:00
if( nBits == -1 )
{
2016-11-17 22:00:00 +01:00
sb->nDataBits = nBytes << 3;
2010-07-26 22:00:00 +02:00
}
else
{
2010-08-05 22:00:00 +02:00
Assert( nBits <= nBytes * 8 );
2016-11-17 22:00:00 +01:00
sb->nDataBits = nBits;
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
sb->iCurBit = iStartBit;
sb->bOverflow = false;
2010-07-26 22:00:00 +02:00
}
2010-08-04 22:00:00 +02:00
/*
=======================
MSG_Clear
for clearing overflowed buffer
=======================
*/
2016-11-17 22:00:00 +01:00
void MSG_Clear( sizebuf_t *sb )
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
sb->iCurBit = 0;
sb->bOverflow = false;
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
static qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
if( sb->iCurBit + nBits > sb->nDataBits )
sb->bOverflow = true;
return sb->bOverflow;
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
qboolean MSG_CheckOverflow( sizebuf_t *sb )
2010-08-04 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
return MSG_Overflow( sb, 0 );
2010-08-04 22:00:00 +02:00
}
2018-03-11 22:00:00 +01:00
int MSG_SeekToBit( sizebuf_t *sb, int bitPos, int whence )
2010-07-26 22:00:00 +02:00
{
2018-03-11 22:00:00 +01:00
// compute the file offset
switch( whence )
{
case SEEK_CUR:
bitPos += sb->iCurBit;
break;
case SEEK_SET:
break;
case SEEK_END:
bitPos += sb->nDataBits;
break;
default:
return -1;
}
if( bitPos < 0 || bitPos > sb->nDataBits )
return -1;
2016-11-17 22:00:00 +01:00
sb->iCurBit = bitPos;
2018-03-11 22:00:00 +01:00
return 0;
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_SeekToByte( sizebuf_t *sb, int bytePos )
2010-08-04 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
sb->iCurBit = bytePos << 3;
2010-08-04 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
if( !MSG_Overflow( sb, 1 ))
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
if( nValue ) sb->pData[sb->iCurBit>>3] |= BIT( sb->iCurBit & 7 );
else sb->pData[sb->iCurBit>>3] &= ~BIT( sb->iCurBit & 7 );
2010-07-26 22:00:00 +02:00
2016-11-17 22:00:00 +01:00
sb->iCurBit++;
2010-07-26 22:00:00 +02:00
}
}
2016-11-17 22:00:00 +01:00
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits )
2010-07-26 22:00:00 +02:00
{
2010-08-06 22:00:00 +02:00
Assert( numbits >= 0 && numbits <= 32 );
2010-07-26 22:00:00 +02:00
// bounds checking..
2016-11-17 22:00:00 +01:00
if(( sb->iCurBit + numbits ) > sb->nDataBits )
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
sb->bOverflow = true;
sb->iCurBit = sb->nDataBits;
2010-07-26 22:00:00 +02:00
}
else
{
int nBitsLeft = numbits;
2016-11-17 22:00:00 +01:00
int iCurBit = sb->iCurBit;
2010-07-26 22:00:00 +02:00
uint iDWord = iCurBit >> 5; // Mask in a dword.
dword iCurBitMasked;
int nBitsWritten;
2016-11-17 22:00:00 +01:00
Assert(( iDWord * 4 + sizeof( long )) <= (uint)MSG_GetMaxBytes( sb ));
2010-07-26 22:00:00 +02:00
iCurBitMasked = iCurBit & 31;
2016-11-17 22:00:00 +01:00
((dword *)sb->pData)[iDWord] &= BitWriteMasks[iCurBitMasked][nBitsLeft];
((dword *)sb->pData)[iDWord] |= curData << iCurBitMasked;
2010-07-26 22:00:00 +02:00
// did it span a dword?
nBitsWritten = 32 - iCurBitMasked;
if( nBitsWritten < nBitsLeft )
{
nBitsLeft -= nBitsWritten;
iCurBit += nBitsWritten;
curData >>= nBitsWritten;
iCurBitMasked = iCurBit & 31;
2016-11-17 22:00:00 +01:00
((dword *)sb->pData)[iDWord+1] &= BitWriteMasks[iCurBitMasked][nBitsLeft];
((dword *)sb->pData)[iDWord+1] |= curData << iCurBitMasked;
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
sb->iCurBit += numbits;
2010-07-26 22:00:00 +02:00
}
}
/*
=======================
2016-11-14 22:00:00 +01:00
MSG_WriteSBitLong
2010-07-26 22:00:00 +02:00
sign bit comes first
=======================
*/
2016-11-17 22:00:00 +01:00
void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits )
2010-07-26 22:00:00 +02:00
{
// do we have a valid # of bits to encode with?
2016-11-17 22:00:00 +01:00
Assert( numbits >= 1 && numbits <= 32 );
2010-07-26 22:00:00 +02:00
// NOTE: it does this wierdness here so it's bit-compatible with regular integer data in the buffer.
// (Some old code writes direct integers right into the buffer).
if( data < 0 )
{
2016-11-17 22:00:00 +01:00
MSG_WriteUBitLong( sb, (uint)( 0x80000000 + data ), numbits - 1 );
MSG_WriteOneBit( sb, 1 );
2010-07-26 22:00:00 +02:00
}
else
{
2016-11-17 22:00:00 +01:00
MSG_WriteUBitLong( sb, (uint)data, numbits - 1 );
MSG_WriteOneBit( sb, 0 );
2010-07-26 22:00:00 +02:00
}
}
2019-03-15 22:00:00 +01:00
void MSG_WriteBitLong( sizebuf_t *sb, int data, int numbits, qboolean bSigned )
2010-07-26 22:00:00 +02:00
{
if( bSigned )
2019-03-15 22:00:00 +01:00
MSG_WriteSBitLong( sb, data, numbits );
else MSG_WriteUBitLong( sb, (uint)data, numbits );
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
2010-07-26 22:00:00 +02:00
{
byte *pOut = (byte *)pData;
int nBitsLeft = nBits;
// get output dword-aligned.
while((( dword )pOut & 3 ) != 0 && nBitsLeft >= 8 )
{
2016-11-17 22:00:00 +01:00
MSG_WriteUBitLong( sb, *pOut, 8 );
2010-07-26 22:00:00 +02:00
nBitsLeft -= 8;
++pOut;
}
// read dwords.
while( nBitsLeft >= 32 )
{
2016-11-17 22:00:00 +01:00
MSG_WriteUBitLong( sb, *(( dword *)pOut ), 32 );
2010-07-26 22:00:00 +02:00
pOut += sizeof( dword );
nBitsLeft -= 32;
}
// read the remaining bytes.
while( nBitsLeft >= 8 )
{
2016-11-17 22:00:00 +01:00
MSG_WriteUBitLong( sb, *pOut, 8 );
2010-07-26 22:00:00 +02:00
nBitsLeft -= 8;
++pOut;
}
// Read the remaining bits.
if( nBitsLeft )
{
2016-11-17 22:00:00 +01:00
MSG_WriteUBitLong( sb, *pOut, nBitsLeft );
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
return !sb->bOverflow;
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits )
2010-07-26 22:00:00 +02:00
{
uint mask, shift;
int d;
2010-08-04 22:00:00 +02:00
// clamp the angle before receiving
2015-12-04 22:00:00 +01:00
fAngle = fmod( fAngle, 360.0f );
if( fAngle < 0 ) fAngle += 360.0f;
2010-08-04 22:00:00 +02:00
2010-07-26 22:00:00 +02:00
shift = ( 1 << numbits );
mask = shift - 1;
2015-12-04 22:00:00 +01:00
d = (int)(( fAngle * shift ) / 360.0f );
2010-07-26 22:00:00 +02:00
d &= mask;
2016-11-17 22:00:00 +01:00
MSG_WriteUBitLong( sb, (uint)d, numbits );
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_WriteCoord( sizebuf_t *sb, float val )
2012-05-23 22:00:00 +02:00
{
// g-cont. we loose precision here but keep old size of coord variable!
2016-11-17 22:00:00 +01:00
if( FBitSet( host.features, ENGINE_WRITE_LARGE_COORD ))
2018-06-15 23:00:00 +02:00
MSG_WriteShort( sb, Q_rint( val ));
2016-11-17 22:00:00 +01:00
else MSG_WriteShort( sb, (int)( val * 8.0f ));
2012-05-23 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_WriteVec3Coord( sizebuf_t *sb, const float *fa )
2012-12-16 21:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
MSG_WriteCoord( sb, fa[0] );
MSG_WriteCoord( sb, fa[1] );
MSG_WriteCoord( sb, fa[2] );
2012-12-16 21:00:00 +01:00
}
2018-03-05 22:00:00 +01:00
void MSG_WriteVec3Angles( sizebuf_t *sb, const float *fa )
{
MSG_WriteBitAngle( sb, fa[0], 16 );
MSG_WriteBitAngle( sb, fa[1], 16 );
MSG_WriteBitAngle( sb, fa[2], 16 );
}
2016-11-17 22:00:00 +01:00
void MSG_WriteBitFloat( sizebuf_t *sb, float val )
2010-07-26 22:00:00 +02:00
{
long intVal;
2016-12-12 22:00:00 +01:00
Assert( sizeof( long ) == sizeof( float ));
Assert( sizeof( float ) == 4 );
2010-07-26 22:00:00 +02:00
intVal = *((long *)&val );
2016-11-17 22:00:00 +01:00
MSG_WriteUBitLong( sb, intVal, 32 );
2010-07-26 22:00:00 +02:00
}
2017-02-05 22:00:00 +01:00
void MSG_WriteCmdExt( sizebuf_t *sb, int cmd, netsrc_t type, const char *name )
{
2017-02-07 22:00:00 +01:00
#ifdef DEBUG_NET_MESSAGES_SEND
2017-02-05 22:00:00 +01:00
if( name != NULL )
{
// get custom name
2018-03-03 22:00:00 +01:00
Con_Printf( "^1sv^7 write: %s\n", name );
2017-02-05 22:00:00 +01:00
}
else if( type == NS_SERVER )
{
2017-02-07 22:00:00 +01:00
if( cmd >= 0 && cmd <= svc_lastmsg )
2017-02-05 22:00:00 +01:00
{
// get engine message name
2018-03-03 22:00:00 +01:00
Con_Printf( "^1sv^7 write: %s\n", svc_strings[cmd] );
2017-02-05 22:00:00 +01:00
}
}
else if( type == NS_CLIENT )
{
2017-02-07 22:00:00 +01:00
if( cmd >= 0 && cmd <= clc_lastmsg )
2017-02-05 22:00:00 +01:00
{
2018-03-03 22:00:00 +01:00
Con_Printf( "^1cl^7 write: %s\n", clc_strings[cmd] );
2017-02-05 22:00:00 +01:00
}
}
#endif
MSG_WriteUBitLong( sb, cmd, sizeof( byte ) << 3 );
}
2016-11-17 22:00:00 +01:00
void MSG_WriteChar( sizebuf_t *sb, int val )
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
MSG_WriteSBitLong( sb, val, sizeof( char ) << 3 );
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_WriteByte( sizebuf_t *sb, int val )
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
MSG_WriteUBitLong( sb, val, sizeof( byte ) << 3 );
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_WriteShort( sizebuf_t *sb, int val )
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
MSG_WriteSBitLong( sb, val, sizeof(short ) << 3 );
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_WriteWord( sizebuf_t *sb, int val )
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
MSG_WriteUBitLong( sb, val, sizeof( word ) << 3 );
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_WriteLong( sizebuf_t *sb, long val )
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
MSG_WriteSBitLong( sb, val, sizeof( long ) << 3 );
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_WriteDword( sizebuf_t *sb, dword val )
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
MSG_WriteUBitLong( sb, val, sizeof( dword ) << 3 );
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_WriteFloat( sizebuf_t *sb, float val )
2010-07-26 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
MSG_WriteBits( sb, &val, sizeof( val ) << 3 );
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
qboolean MSG_WriteBytes( sizebuf_t *sb, const void *pBuf, int nBytes )
{
return MSG_WriteBits( sb, pBuf, nBytes << 3 );
}
qboolean MSG_WriteString( sizebuf_t *sb, const char *pStr )
2010-07-26 22:00:00 +02:00
{
if( pStr )
{
do
{
2016-11-17 22:00:00 +01:00
MSG_WriteChar( sb, *pStr );
2010-08-04 22:00:00 +02:00
pStr++;
} while( *( pStr - 1 ));
2010-07-26 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
else MSG_WriteChar( sb, 0 );
2010-08-04 22:00:00 +02:00
2016-11-17 22:00:00 +01:00
return !sb->bOverflow;
2010-07-31 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
int MSG_ReadOneBit( sizebuf_t *sb )
2010-07-31 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
if( !MSG_Overflow( sb, 1 ))
2010-07-31 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
int value = sb->pData[sb->iCurBit >> 3] & (1 << ( sb->iCurBit & 7 ));
sb->iCurBit++;
2010-07-31 22:00:00 +02:00
return !!value;
}
return 0;
}
2016-11-17 22:00:00 +01:00
uint MSG_ReadUBitLong( sizebuf_t *sb, int numbits )
2010-07-31 22:00:00 +02:00
{
int idword1;
uint dword1, ret;
2010-08-04 22:00:00 +02:00
if( numbits == 8 )
{
2016-11-17 22:00:00 +01:00
int leftBits = MSG_GetNumBitsLeft( sb );
2010-08-04 22:00:00 +02:00
if( leftBits >= 0 && leftBits < 8 )
return 0; // end of message
}
2016-11-17 22:00:00 +01:00
if(( sb->iCurBit + numbits ) > sb->nDataBits )
2010-07-31 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
sb->bOverflow = true;
sb->iCurBit = sb->nDataBits;
2010-07-31 22:00:00 +02:00
return 0;
}
2016-12-12 22:00:00 +01:00
Assert( numbits > 0 && numbits <= 32 );
2010-07-31 22:00:00 +02:00
// Read the current dword.
2016-11-17 22:00:00 +01:00
idword1 = sb->iCurBit >> 5;
dword1 = ((uint *)sb->pData)[idword1];
dword1 >>= ( sb->iCurBit & 31 ); // get the bits we're interested in.
2010-07-31 22:00:00 +02:00
2016-11-17 22:00:00 +01:00
sb->iCurBit += numbits;
2010-07-31 22:00:00 +02:00
ret = dword1;
// Does it span this dword?
2016-11-17 22:00:00 +01:00
if(( sb->iCurBit - 1 ) >> 5 == idword1 )
2010-07-31 22:00:00 +02:00
{
if( numbits != 32 )
ret &= ExtraMasks[numbits];
}
else
{
2016-11-17 22:00:00 +01:00
int nExtraBits = sb->iCurBit & 31;
uint dword2 = ((uint *)sb->pData)[idword1+1] & ExtraMasks[nExtraBits];
2010-07-31 22:00:00 +02:00
// no need to mask since we hit the end of the dword.
// shift the second dword's part into the high bits.
ret |= (dword2 << ( numbits - nExtraBits ));
}
return ret;
}
2016-11-17 22:00:00 +01:00
float MSG_ReadBitFloat( sizebuf_t *sb )
2010-07-31 22:00:00 +02:00
{
long val;
int bit, byte;
2016-12-12 22:00:00 +01:00
Assert( sizeof( float ) == sizeof( long ));
Assert( sizeof( float ) == 4 );
2010-07-31 22:00:00 +02:00
2016-11-17 22:00:00 +01:00
if( MSG_Overflow( sb, 32 ))
2010-07-31 22:00:00 +02:00
return 0.0f;
2016-11-17 22:00:00 +01:00
bit = sb->iCurBit & 0x7;
byte = sb->iCurBit >> 3;
2010-07-31 22:00:00 +02:00
2016-11-17 22:00:00 +01:00
val = sb->pData[byte] >> bit;
val |= ((int)sb->pData[byte + 1]) << ( 8 - bit );
val |= ((int)sb->pData[byte + 2]) << ( 16 - bit );
val |= ((int)sb->pData[byte + 3]) << ( 24 - bit );
2010-07-31 22:00:00 +02:00
if( bit != 0 )
2016-11-17 22:00:00 +01:00
val |= ((int)sb->pData[byte + 4]) << ( 32 - bit );
sb->iCurBit += 32;
2010-07-31 22:00:00 +02:00
return *((float *)&val);
}
2016-11-17 22:00:00 +01:00
qboolean MSG_ReadBits( sizebuf_t *sb, void *pOutData, int nBits )
2010-07-31 22:00:00 +02:00
{
byte *pOut = (byte *)pOutData;
int nBitsLeft = nBits;
// get output dword-aligned.
while((( dword )pOut & 3) != 0 && nBitsLeft >= 8 )
{
2016-11-17 22:00:00 +01:00
*pOut = (byte)MSG_ReadUBitLong( sb, 8 );
2010-07-31 22:00:00 +02:00
++pOut;
nBitsLeft -= 8;
}
// read dwords.
while( nBitsLeft >= 32 )
{
2016-11-17 22:00:00 +01:00
*((dword *)pOut) = MSG_ReadUBitLong( sb, 32 );
2010-07-31 22:00:00 +02:00
pOut += sizeof( dword );
nBitsLeft -= 32;
}
// read the remaining bytes.
while( nBitsLeft >= 8 )
{
2016-11-17 22:00:00 +01:00
*pOut = MSG_ReadUBitLong( sb, 8 );
2010-07-31 22:00:00 +02:00
++pOut;
nBitsLeft -= 8;
}
// read the remaining bits.
if( nBitsLeft )
{
2016-11-17 22:00:00 +01:00
*pOut = MSG_ReadUBitLong( sb, nBitsLeft );
2010-07-31 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
return !sb->bOverflow;
2010-07-31 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
float MSG_ReadBitAngle( sizebuf_t *sb, int numbits )
2010-07-31 22:00:00 +02:00
{
float fReturn, shift;
int i;
shift = (float)( 1 << numbits );
2016-11-17 22:00:00 +01:00
i = MSG_ReadUBitLong( sb, numbits );
2011-04-18 22:00:00 +02:00
fReturn = (float)i * ( 360.0f / shift );
2010-07-31 22:00:00 +02:00
2010-08-04 22:00:00 +02:00
// clamp the finale angle
2011-04-18 22:00:00 +02:00
if( fReturn < -180.0f ) fReturn += 360.0f;
else if( fReturn > 180.0f ) fReturn -= 360.0f;
2010-08-04 22:00:00 +02:00
2010-07-31 22:00:00 +02:00
return fReturn;
}
// Append numbits least significant bits from data to the current bit stream
2016-11-17 22:00:00 +01:00
int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
2010-07-31 22:00:00 +02:00
{
int r, sign;
2016-11-17 22:00:00 +01:00
r = MSG_ReadUBitLong( sb, numbits - 1 );
2010-07-31 22:00:00 +02:00
// NOTE: it does this wierdness here so it's bit-compatible with regular integer data in the buffer.
// (Some old code writes direct integers right into the buffer).
2016-11-17 22:00:00 +01:00
sign = MSG_ReadOneBit( sb );
2011-04-08 22:00:00 +02:00
if( sign ) r = -( BIT( numbits - 1 ) - r );
2010-07-31 22:00:00 +02:00
return r;
}
2016-11-17 22:00:00 +01:00
uint MSG_ReadBitLong( sizebuf_t *sb, int numbits, qboolean bSigned )
2010-07-31 22:00:00 +02:00
{
if( bSigned )
2016-11-17 22:00:00 +01:00
return (uint)MSG_ReadSBitLong( sb, numbits );
return MSG_ReadUBitLong( sb, numbits );
2010-07-31 22:00:00 +02:00
}
2017-02-05 22:00:00 +01:00
int MSG_ReadCmd( sizebuf_t *sb, netsrc_t type )
{
int cmd = MSG_ReadUBitLong( sb, sizeof( byte ) << 3 );
2017-02-07 22:00:00 +01:00
#ifdef DEBUG_NET_MESSAGES_READ
2017-02-05 22:00:00 +01:00
if( type == NS_SERVER )
{
2018-03-03 22:00:00 +01:00
Con_Printf( "^1cl^7 read: %s\n", CL_MsgInfo( cmd ));
2017-02-05 22:00:00 +01:00
}
2017-02-07 22:00:00 +01:00
else if( cmd >= 0 && cmd <= clc_lastmsg )
2017-02-05 22:00:00 +01:00
{
2018-03-03 22:00:00 +01:00
Con_Printf( "^1sv^7 read: %s\n", clc_strings[cmd] );
2017-02-05 22:00:00 +01:00
}
#endif
return cmd;
}
2016-11-17 22:00:00 +01:00
int MSG_ReadChar( sizebuf_t *sb )
2010-07-31 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
return MSG_ReadSBitLong( sb, sizeof( char ) << 3 );
2010-07-31 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
int MSG_ReadByte( sizebuf_t *sb )
2010-07-31 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
return MSG_ReadUBitLong( sb, sizeof( byte ) << 3 );
2010-07-31 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
int MSG_ReadShort( sizebuf_t *sb )
2010-07-31 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
return MSG_ReadSBitLong( sb, sizeof( short ) << 3 );
2010-07-31 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
int MSG_ReadWord( sizebuf_t *sb )
2010-07-31 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
return MSG_ReadUBitLong( sb, sizeof( word ) << 3 );
2010-07-31 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
float MSG_ReadCoord( sizebuf_t *sb )
2012-05-21 22:00:00 +02:00
{
// g-cont. we loose precision here but keep old size of coord variable!
2016-11-17 22:00:00 +01:00
if( FBitSet( host.features, ENGINE_WRITE_LARGE_COORD ))
2018-06-15 23:00:00 +02:00
return (float)(MSG_ReadShort( sb ));
2016-11-17 22:00:00 +01:00
return (float)(MSG_ReadShort( sb ) * ( 1.0f / 8.0f ));
}
void MSG_ReadVec3Coord( sizebuf_t *sb, vec3_t fa )
{
fa[0] = MSG_ReadCoord( sb );
fa[1] = MSG_ReadCoord( sb );
fa[2] = MSG_ReadCoord( sb );
2012-05-21 22:00:00 +02:00
}
2018-03-05 22:00:00 +01:00
void MSG_ReadVec3Angles( sizebuf_t *sb, vec3_t fa )
{
fa[0] = MSG_ReadBitAngle( sb, 16 );
fa[1] = MSG_ReadBitAngle( sb, 16 );
fa[2] = MSG_ReadBitAngle( sb, 16 );
}
2016-11-17 22:00:00 +01:00
long MSG_ReadLong( sizebuf_t *sb )
2012-12-16 21:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
return MSG_ReadSBitLong( sb, sizeof( long ) << 3 );
2012-12-16 21:00:00 +01:00
}
2016-11-17 22:00:00 +01:00
dword MSG_ReadDword( sizebuf_t *sb )
2010-07-31 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
return MSG_ReadUBitLong( sb, sizeof( dword ) << 3 );
2010-07-31 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
float MSG_ReadFloat( sizebuf_t *sb )
2010-07-31 22:00:00 +02:00
{
float ret;
2016-12-12 22:00:00 +01:00
Assert( sizeof( ret ) == 4 );
2010-07-31 22:00:00 +02:00
2016-11-17 22:00:00 +01:00
MSG_ReadBits( sb, &ret, 32 );
2010-07-31 22:00:00 +02:00
return ret;
}
2016-11-17 22:00:00 +01:00
qboolean MSG_ReadBytes( sizebuf_t *sb, void *pOut, int nBytes )
2010-07-31 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
return MSG_ReadBits( sb, pOut, nBytes << 3 );
2010-07-31 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine )
2010-07-31 22:00:00 +02:00
{
2017-07-18 23:00:00 +02:00
static char string[2048];
2010-08-04 22:00:00 +02:00
int l = 0, c;
do
2010-07-31 22:00:00 +02:00
{
2016-11-14 22:00:00 +01:00
// use MSG_ReadByte so -1 is out of bounds
2016-11-17 22:00:00 +01:00
c = MSG_ReadByte( sb );
2010-07-31 22:00:00 +02:00
2010-08-04 22:00:00 +02:00
if( c == 0 ) break;
else if( bLine && c == '\n' )
2010-07-31 22:00:00 +02:00
break;
// translate all fmt spec to avoid crash bugs
2011-04-08 22:00:00 +02:00
// NOTE: but game strings leave unchanged. see pfnWriteString for details
2010-08-04 22:00:00 +02:00
if( c == '%' ) c = '.';
2010-07-31 22:00:00 +02:00
2010-08-04 22:00:00 +02:00
string[l] = c;
l++;
} while( l < sizeof( string ) - 1 );
string[l] = 0; // terminator
2010-07-31 22:00:00 +02:00
return string;
2010-10-07 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove )
2010-10-07 22:00:00 +02:00
{
int i, endbit = startbit + bitstoremove;
2016-11-17 22:00:00 +01:00
int remaining_to_end = sb->nDataBits - endbit;
2010-10-07 22:00:00 +02:00
sizebuf_t temp;
2018-03-08 22:00:00 +01:00
MSG_StartWriting( &temp, sb->pData, MSG_GetMaxBytes( sb ), startbit, -1 );
2018-03-11 22:00:00 +01:00
MSG_SeekToBit( sb, endbit, SEEK_SET );
2010-10-07 22:00:00 +02:00
for( i = 0; i < remaining_to_end; i++ )
{
2016-11-17 22:00:00 +01:00
MSG_WriteOneBit( &temp, MSG_ReadOneBit( sb ));
2010-10-07 22:00:00 +02:00
}
2018-03-11 22:00:00 +01:00
MSG_SeekToBit( sb, startbit, SEEK_SET );
2016-11-17 22:00:00 +01:00
sb->nDataBits -= bitstoremove;
2010-07-26 22:00:00 +02:00
}