summaryrefslogtreecommitdiff
path: root/engine/dt.h
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /engine/dt.h
downloadarchived-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.h521
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