diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /engine/dt.h | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'engine/dt.h')
| -rw-r--r-- | engine/dt.h | 521 |
1 files changed, 521 insertions, 0 deletions
diff --git a/engine/dt.h b/engine/dt.h new file mode 100644 index 0000000..a54f06d --- /dev/null +++ b/engine/dt.h @@ -0,0 +1,521 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef DATATABLE_H +#define DATATABLE_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "dt_common.h" +#include "dt_recv_eng.h" +#include "dt_send_eng.h" +#include "utlvector.h" +#include "dt_encode.h" +#include "utlmap.h" +#include "tier1/bitbuf.h" + + +class SendTable; +class RecvTable; +class CDTISendTable; + + + +#define MAX_EXCLUDE_PROPS 512 + + +// Bit counts used to encode the information about a property. +#define PROPINFOBITS_NUMPROPS 10 +#define PROPINFOBITS_TYPE 5 +#define PROPINFOBITS_FLAGS SPROP_NUMFLAGBITS_NETWORKED +#define PROPINFOBITS_STRINGBUFFERLEN 10 +#define PROPINFOBITS_NUMBITS 7 +#define PROPINFOBITS_RIGHTSHIFT 6 +#define PROPINFOBITS_NUMELEMENTS 10 // For arrays. + + + +class ExcludeProp +{ +public: + char const *m_pTableName; + char const *m_pPropName; +}; + + +// ------------------------------------------------------------------------------------ // +// CDeltaBitsReader. +// ------------------------------------------------------------------------------------ // + + +class CDeltaBitsReader +{ +public: + CDeltaBitsReader( bf_read *pBuf ); + ~CDeltaBitsReader(); + + // Write the next property index. Returns the number of bits used. + unsigned int ReadNextPropIndex(); + unsigned int ReadNextPropIndex_Continued(); + void SkipPropData( const SendProp *pProp ); + int ComparePropData( CDeltaBitsReader* pOut, const SendProp *pProp ); + void CopyPropData( bf_write* pOut, const SendProp *pProp ); + + // If you know you're done but you're not at the end (you haven't called until + // ReadNextPropIndex returns -1), call this so it won't assert in its destructor. + void ForceFinished(); + +private: + bf_read *m_pBuf; + int m_iLastProp; +}; + + +FORCEINLINE CDeltaBitsReader::CDeltaBitsReader( bf_read *pBuf ) +{ + m_pBuf = pBuf; + m_iLastProp = -1; +} + +FORCEINLINE CDeltaBitsReader::~CDeltaBitsReader() +{ + // Make sure they read to the end unless they specifically said they don't care. + Assert( !m_pBuf ); +} + +FORCEINLINE void CDeltaBitsReader::ForceFinished() +{ +#ifdef DBGFLAG_ASSERT + m_pBuf = NULL; +#endif +} + +FORCEINLINE unsigned int CDeltaBitsReader::ReadNextPropIndex() +{ + Assert( m_pBuf ); + // Expanded and optimized version of + // if ( m_pBuf->ReadOneBit() ) + // { + // m_iLastProp += 1 + m_pBuf->ReadUBitVar(); + // return m_iLastProp; + // } + // return ~0u; + if ( m_pBuf->GetNumBitsLeft() >= 7 ) + { + uint bits = m_pBuf->ReadUBitLong( 7 ); + if ( bits & 1 ) + { + uint delta = bits >> 3; + if ( bits & 6 ) + { + delta = m_pBuf->ReadUBitVarInternal( (bits & 6) >> 1 ); + } + m_iLastProp = m_iLastProp + 1 + delta; + Assert( m_iLastProp < MAX_DATATABLE_PROPS ); + return m_iLastProp; + } + m_pBuf->m_iCurBit -= 6; // Unread six bits we shouldn't have looked at + } + else + { + // Not enough bits for a property index. + if ( m_pBuf->ReadOneBit() ) + { + // Expected a zero bit! Force an overflow! + m_pBuf->Seek(-1); + } + } + ForceFinished(); + return ~0u; +} + +FORCEINLINE void CDeltaBitsReader::SkipPropData( const SendProp *pProp ) +{ + g_PropTypeFns[ pProp->GetType() ].SkipProp( pProp, m_pBuf ); +} + +FORCEINLINE void CDeltaBitsReader::CopyPropData( bf_write* pOut, const SendProp *pProp ) +{ + int start = m_pBuf->GetNumBitsRead(); + g_PropTypeFns[ pProp->GetType() ].SkipProp( pProp, m_pBuf ); + int len = m_pBuf->GetNumBitsRead() - start; + m_pBuf->Seek( start ); + pOut->WriteBitsFromBuffer( m_pBuf, len ); +} + +FORCEINLINE int CDeltaBitsReader::ComparePropData( CDeltaBitsReader *pInReader, const SendProp *pProp ) +{ + bf_read *pIn = pInReader->m_pBuf; + return g_PropTypeFns[pProp->m_Type].CompareDeltas( pProp, m_pBuf, pIn ); +} + + +// ------------------------------------------------------------------------------------ // +// CDeltaBitsWriter. +// ------------------------------------------------------------------------------------ // + +class CDeltaBitsWriter +{ +public: + CDeltaBitsWriter( bf_write *pBuf ); + ~CDeltaBitsWriter(); + + // Write the next property index. Returns the number of bits used. + void WritePropIndex( int iProp ); + + // Access the buffer it's outputting to. + bf_write* GetBitBuf(); + +private: + bf_write *m_pBuf; + int m_iLastProp; +}; + +inline CDeltaBitsWriter::CDeltaBitsWriter( bf_write *pBuf ) +{ + m_pBuf = pBuf; + m_iLastProp = -1; +} + +inline bf_write* CDeltaBitsWriter::GetBitBuf() +{ + return m_pBuf; +} + +FORCEINLINE void CDeltaBitsWriter::WritePropIndex( int iProp ) +{ + Assert( iProp >= 0 && iProp < MAX_DATATABLE_PROPS ); + unsigned int diff = iProp - m_iLastProp; + m_iLastProp = iProp; + Assert( diff > 0 && diff <= MAX_DATATABLE_PROPS ); + // Expanded inline for maximum efficiency. + //m_pBuf->WriteOneBit( 1 ); + //m_pBuf->WriteUBitVar( diff - 1 ); + COMPILE_TIME_ASSERT( MAX_DATATABLE_PROPS <= 0x1000u ); + int n = ((diff < 0x11u) ? -1 : 0) + ((diff < 0x101u) ? -1 : 0); + m_pBuf->WriteUBitLong( diff*8 - 8 + 4 + n*2 + 1, 8 + n*4 + 4 + 2 + 1 ); +} + +inline CDeltaBitsWriter::~CDeltaBitsWriter() +{ + m_pBuf->WriteOneBit( 0 ); +} + + +// ----------------------------------------------------------------------------- // +// +// CSendNode +// +// Each datatable gets a tree of CSendNodes. There is one CSendNode +// for each datatable property that was in the original SendTable. +// +// ----------------------------------------------------------------------------- // + +class CSendNode +{ +public: + + CSendNode(); + ~CSendNode(); + + int GetNumChildren() const; + CSendNode* GetChild( int i ) const; + + + // Returns true if the specified prop is in this node or any of its children. + bool IsPropInRecursiveProps( int i ) const; + + // Each datatable property (without SPROP_PROXY_ALWAYS_YES set) gets a unique index here. + // The engine stores arrays of CSendProxyRecipients with the results of the proxies and indexes the results + // with this index. + // + // Returns DATATABLE_PROXY_INDEX_NOPROXY if the property has SPROP_PROXY_ALWAYS_YES set. + unsigned short GetDataTableProxyIndex() const; + void SetDataTableProxyIndex( unsigned short val ); + + // Similar to m_DataTableProxyIndex, but doesn't use DATATABLE_PROXY_INDEX_INVALID, + // so this can be used to index CDataTableStack::m_pProxies. + unsigned short GetRecursiveProxyIndex() const; + void SetRecursiveProxyIndex( unsigned short val ); + + +public: + + // Child datatables. + CUtlVector<CSendNode*> m_Children; + + // The datatable property that leads us to this CSendNode. + // This indexes the CSendTablePrecalc or CRecvDecoder's m_DatatableProps list. + // The root CSendNode sets this to -1. + short m_iDatatableProp; + + // The SendTable that this node represents. + // ALL CSendNodes have this. + const SendTable *m_pTable; + + // + // Properties in this table. + // + + // m_iFirstRecursiveProp to m_nRecursiveProps defines the list of propertise + // of this node and all its children. + unsigned short m_iFirstRecursiveProp; + unsigned short m_nRecursiveProps; + + + // See GetDataTableProxyIndex(). + unsigned short m_DataTableProxyIndex; + + // See GetRecursiveProxyIndex(). + unsigned short m_RecursiveProxyIndex; +}; + + +inline int CSendNode::GetNumChildren() const +{ + return m_Children.Count(); +} + +inline CSendNode* CSendNode::GetChild( int i ) const +{ + return m_Children[i]; +} + + +inline bool CSendNode::IsPropInRecursiveProps( int i ) const +{ + int index = i - (int)m_iFirstRecursiveProp; + return index >= 0 && index < m_nRecursiveProps; +} + +inline unsigned short CSendNode::GetDataTableProxyIndex() const +{ + Assert( m_DataTableProxyIndex != DATATABLE_PROXY_INDEX_INVALID ); // Make sure it's been set before. + return m_DataTableProxyIndex; +} + +inline void CSendNode::SetDataTableProxyIndex( unsigned short val ) +{ + m_DataTableProxyIndex = val; +} + +inline unsigned short CSendNode::GetRecursiveProxyIndex() const +{ + return m_RecursiveProxyIndex; +} + +inline void CSendNode::SetRecursiveProxyIndex( unsigned short val ) +{ + m_RecursiveProxyIndex = val; +} + + + +class CFastLocalTransferPropInfo +{ +public: + unsigned short m_iRecvOffset; + unsigned short m_iSendOffset; + unsigned short m_iProp; +}; + + +class CFastLocalTransferInfo +{ +public: + CUtlVector<CFastLocalTransferPropInfo> m_FastInt32; + CUtlVector<CFastLocalTransferPropInfo> m_FastInt16; + CUtlVector<CFastLocalTransferPropInfo> m_FastInt8; + CUtlVector<CFastLocalTransferPropInfo> m_FastVector; + CUtlVector<CFastLocalTransferPropInfo> m_OtherProps; // Props that must be copied slowly (proxies and all). +}; + + +// ----------------------------------------------------------------------------- // +// CSendTablePrecalc +// ----------------------------------------------------------------------------- // +class CSendTablePrecalc +{ +public: + CSendTablePrecalc(); + virtual ~CSendTablePrecalc(); + + // This function builds the flat property array given a SendTable. + bool SetupFlatPropertyArray(); + + int GetNumProps() const; + const SendProp* GetProp( int i ) const; + + int GetNumDatatableProps() const; + const SendProp* GetDatatableProp( int i ) const; + + SendTable* GetSendTable() const; + CSendNode* GetRootNode(); + + int GetNumDataTableProxies() const; + void SetNumDataTableProxies( int count ); + + +public: + + class CProxyPathEntry + { + public: + unsigned short m_iDatatableProp; // Lookup into CSendTablePrecalc or CRecvDecoder::m_DatatableProps. + unsigned short m_iProxy; + }; + class CProxyPath + { + public: + unsigned short m_iFirstEntry; // Index into m_ProxyPathEntries. + unsigned short m_nEntries; + }; + + CUtlVector<CProxyPathEntry> m_ProxyPathEntries; // For each proxy index, this is all the DT proxies that generate it. + CUtlVector<CProxyPath> m_ProxyPaths; // CProxyPathEntries lookup into this. + + // These are what CSendNodes reference. + // These are actual data properties (ints, floats, etc). + CUtlVector<const SendProp*> m_Props; + + // Each datatable in a SendTable's tree gets a proxy index, and its properties reference that. + CUtlVector<unsigned char> m_PropProxyIndices; + + // CSendNode::m_iDatatableProp indexes this. + // These are the datatable properties (SendPropDataTable). + CUtlVector<const SendProp*> m_DatatableProps; + + // This is the property hierarchy, with the nodes indexing m_Props. + CSendNode m_Root; + + // From whence we came. + SendTable *m_pSendTable; + + // For instrumentation. + CDTISendTable *m_pDTITable; + + // This is precalculated in single player to allow faster direct copying of the entity data + // from the server entity to the client entity. + CFastLocalTransferInfo m_FastLocalTransfer; + + // This tells how many data table properties there are without SPROP_PROXY_ALWAYS_YES. + // Arrays allocated with this size can be indexed by CSendNode::GetDataTableProxyIndex(). + int m_nDataTableProxies; + + // Map prop offsets to indices for properties that can use it. + CUtlMap<unsigned short, unsigned short> m_PropOffsetToIndexMap; +}; + + +inline int CSendTablePrecalc::GetNumProps() const +{ + return m_Props.Count(); +} + +inline const SendProp* CSendTablePrecalc::GetProp( int i ) const +{ + return m_Props[i]; +} + +inline int CSendTablePrecalc::GetNumDatatableProps() const +{ + return m_DatatableProps.Count(); +} + +inline const SendProp* CSendTablePrecalc::GetDatatableProp( int i ) const +{ + return m_DatatableProps[i]; +} + +inline SendTable* CSendTablePrecalc::GetSendTable() const +{ + return m_pSendTable; +} + +inline CSendNode* CSendTablePrecalc::GetRootNode() +{ + return &m_Root; +} + +inline int CSendTablePrecalc::GetNumDataTableProxies() const +{ + return m_nDataTableProxies; +} + + +inline void CSendTablePrecalc::SetNumDataTableProxies( int count ) +{ + m_nDataTableProxies = count; +} + + +// ------------------------------------------------------------------------ // +// Helpers. +// ------------------------------------------------------------------------ // + +// Used internally by various datatable modules. +void DataTable_Warning( PRINTF_FORMAT_STRING const char *pInMessage, ... ) FMTFUNCTION( 1, 2 ); +bool ShouldWatchThisProp( const SendTable *pTable, int objectID, const char *pPropName ); + +// Same as AreBitArraysEqual but does a trivial test to make sure the +// two arrays are equally sized. +bool CompareBitArrays( + void const *pPacked1, + void const *pPacked2, + int nBits1, + int nBits2 + ); + +// to skip of a Property we just IsEncodedZero to read over it +// this is faster then doing a full Decode() +inline void SkipPropData( bf_read *pIn, const SendProp *pProp ) +{ + g_PropTypeFns[ pProp->GetType() ].SkipProp( pProp, pIn ); +} + +// This is to be called on SendTables and RecvTables to setup array properties +// to point at their property templates and to set the SPROP_INSIDEARRAY flag +// on the properties inside arrays. +// We make the proptype an explicit template parameter because +// gcc templating cannot deduce typedefs from classes in templates properly + +template< class TableType, class PropType > +void SetupArrayProps_R( TableType *pTable ) +{ + // If this table has already been initialized in here, then jump out. + if ( pTable->IsInitialized() ) + return; + + pTable->SetInitialized( true ); + + for ( int i=0; i < pTable->GetNumProps(); i++ ) + { + PropType *pProp = pTable->GetProp( i ); + + if ( pProp->GetType() == DPT_Array ) + { + ErrorIfNot( i >= 1, + ("SetupArrayProps_R: array prop '%s' is at index zero.", pProp->GetName()) + ); + + // Get the property defining the elements in the array. + PropType *pArrayProp = pTable->GetProp( i-1 ); + pArrayProp->SetInsideArray(); + pProp->SetArrayProp( pArrayProp ); + } + else if ( pProp->GetType() == DPT_DataTable ) + { + // Recurse into children datatables. + SetupArrayProps_R<TableType,PropType>( pProp->GetDataTable() ); + } + } +} + + +#endif // DATATABLE_H |