Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1382 lines
34 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "quakedef.h"
  8. #include "dt.h"
  9. #include "dt_encode.h"
  10. #include "coordsize.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. extern void DataTable_Warning( const char *pInMessage, ... );
  14. extern bool ShouldWatchThisProp( const SendTable *pTable, int objectID, const char *pPropName );
  15. // The engine implements this.
  16. extern const char* GetObjectClassName( int objectID );
  17. void EncodeFloat( const SendProp *pProp, float fVal, bf_write *pOut, int objectID )
  18. {
  19. // Check for special flags like SPROP_COORD, SPROP_NOSCALE, and SPROP_NORMAL.
  20. int flags = pProp->GetFlags();
  21. if ( flags & SPROP_COORD )
  22. {
  23. pOut->WriteBitCoord( fVal );
  24. }
  25. else if ( flags & ( SPROP_COORD_MP | SPROP_COORD_MP_LOWPRECISION | SPROP_COORD_MP_INTEGRAL ) )
  26. {
  27. COMPILE_TIME_ASSERT( SPROP_COORD_MP_INTEGRAL == (1<<15) );
  28. COMPILE_TIME_ASSERT( SPROP_COORD_MP_LOWPRECISION == (1<<14) );
  29. pOut->WriteBitCoordMP( fVal, ((flags >> 15) & 1), ((flags >> 14) & 1) );
  30. }
  31. else if ( flags & SPROP_NORMAL )
  32. {
  33. pOut->WriteBitNormal( fVal );
  34. }
  35. else // standard clamped-range float
  36. {
  37. unsigned long ulVal;
  38. int nBits = pProp->m_nBits;
  39. if ( flags & SPROP_NOSCALE )
  40. {
  41. union { float f; uint32 u; } convert = { fVal };
  42. ulVal = convert.u;
  43. nBits = 32;
  44. }
  45. else if( fVal < pProp->m_fLowValue )
  46. {
  47. // clamp < 0
  48. ulVal = 0;
  49. if(!(flags & SPROP_ROUNDUP))
  50. {
  51. DataTable_Warning("(class %s): Out-of-range value (%f / %f) in SendPropFloat '%s', clamping.\n",
  52. GetObjectClassName( objectID ), fVal, pProp->m_fLowValue, pProp->m_pVarName );
  53. }
  54. }
  55. else if( fVal > pProp->m_fHighValue )
  56. {
  57. // clamp > 1
  58. ulVal = ((1 << pProp->m_nBits) - 1);
  59. if(!(flags & SPROP_ROUNDDOWN))
  60. {
  61. DataTable_Warning("%s: Out-of-range value (%f/%f) in SendPropFloat '%s', clamping.\n",
  62. GetObjectClassName( objectID ), fVal, pProp->m_fHighValue, pProp->m_pVarName );
  63. }
  64. }
  65. else
  66. {
  67. float fRangeVal = (fVal - pProp->m_fLowValue) * pProp->m_fHighLowMul;
  68. if ( pProp->m_nBits <= 22 )
  69. {
  70. // this is the case we always expect to hit
  71. ulVal = FastFloatToSmallInt( fRangeVal );
  72. }
  73. else
  74. {
  75. // retain old logic just in case anyone relies on its behavior
  76. ulVal = RoundFloatToUnsignedLong( fRangeVal );
  77. }
  78. }
  79. pOut->WriteUBitLong(ulVal, nBits);
  80. }
  81. }
  82. static float DecodeFloat(SendProp const *pProp, bf_read *pIn)
  83. {
  84. int flags = pProp->GetFlags();
  85. if ( flags & SPROP_COORD )
  86. {
  87. return pIn->ReadBitCoord();
  88. }
  89. else if ( flags & ( SPROP_COORD_MP | SPROP_COORD_MP_LOWPRECISION | SPROP_COORD_MP_INTEGRAL ) )
  90. {
  91. return pIn->ReadBitCoordMP( (flags >> 15) & 1, (flags >> 14) & 1 );
  92. }
  93. else if ( flags & SPROP_NOSCALE )
  94. {
  95. return pIn->ReadBitFloat();
  96. }
  97. else if ( flags & SPROP_NORMAL )
  98. {
  99. return pIn->ReadBitNormal();
  100. }
  101. else // standard clamped-range float
  102. {
  103. unsigned long dwInterp = pIn->ReadUBitLong(pProp->m_nBits);
  104. float fVal = (float)dwInterp / ((1 << pProp->m_nBits) - 1);
  105. fVal = pProp->m_fLowValue + (pProp->m_fHighValue - pProp->m_fLowValue) * fVal;
  106. return fVal;
  107. }
  108. }
  109. static inline void DecodeVector(SendProp const *pProp, bf_read *pIn, float *v)
  110. {
  111. v[0] = DecodeFloat(pProp, pIn);
  112. v[1] = DecodeFloat(pProp, pIn);
  113. // Don't read in the third component for normals
  114. if ((pProp->GetFlags() & SPROP_NORMAL) == 0)
  115. {
  116. v[2] = DecodeFloat(pProp, pIn);
  117. }
  118. else
  119. {
  120. int signbit = pIn->ReadOneBit();
  121. float v0v0v1v1 = v[0] * v[0] +
  122. v[1] * v[1];
  123. if (v0v0v1v1 < 1.0f)
  124. v[2] = sqrtf( 1.0f - v0v0v1v1 );
  125. else
  126. v[2] = 0.0f;
  127. if (signbit)
  128. v[2] *= -1.0f;
  129. }
  130. }
  131. static inline void DecodeQuaternion(SendProp const *pProp, bf_read *pIn, float *v)
  132. {
  133. v[0] = DecodeFloat(pProp, pIn);
  134. v[1] = DecodeFloat(pProp, pIn);
  135. v[2] = DecodeFloat(pProp, pIn);
  136. v[3] = DecodeFloat(pProp, pIn);
  137. }
  138. int DecodeBits( DecodeInfo *pInfo, unsigned char *pOut )
  139. {
  140. bf_read temp;
  141. // Read the property in (note: we don't return the bits from here because Decode returns
  142. // the decoded bits.. we're interested in getting the encoded bits).
  143. temp = *pInfo->m_pIn;
  144. pInfo->m_pRecvProp = NULL;
  145. pInfo->m_pData = NULL;
  146. g_PropTypeFns[pInfo->m_pProp->m_Type].Decode( pInfo );
  147. // Return the encoded bits.
  148. int nBits = pInfo->m_pIn->GetNumBitsRead() - temp.GetNumBitsRead();
  149. temp.ReadBits(pOut, nBits);
  150. return nBits;
  151. }
  152. // ---------------------------------------------------------------------------------------- //
  153. // Most of the prop types can use this generic FastCopy version. Arrays are a bit of a pain.
  154. // ---------------------------------------------------------------------------------------- //
  155. inline void Generic_FastCopy(
  156. const SendProp *pSendProp,
  157. const RecvProp *pRecvProp,
  158. const unsigned char *pSendData,
  159. unsigned char *pRecvData,
  160. int objectID )
  161. {
  162. // Get the data out of the ent.
  163. CRecvProxyData recvProxyData;
  164. pSendProp->GetProxyFn()(
  165. pSendProp,
  166. pSendData,
  167. pSendData + pSendProp->GetOffset(),
  168. &recvProxyData.m_Value,
  169. 0,
  170. objectID
  171. );
  172. // Fill in the data for the recv proxy.
  173. recvProxyData.m_pRecvProp = pRecvProp;
  174. recvProxyData.m_iElement = 0;
  175. recvProxyData.m_ObjectID = objectID;
  176. pRecvProp->GetProxyFn()( &recvProxyData, pRecvData, pRecvData + pRecvProp->GetOffset() );
  177. }
  178. // ---------------------------------------------------------------------------------------- //
  179. // DecodeInfo implementation.
  180. // ---------------------------------------------------------------------------------------- //
  181. void DecodeInfo::CopyVars( const DecodeInfo *pOther )
  182. {
  183. m_pStruct = pOther->m_pStruct;
  184. m_pData = pOther->m_pData;
  185. m_pRecvProp = pOther->m_pRecvProp;
  186. m_pProp = pOther->m_pProp;
  187. m_pIn = pOther->m_pIn;
  188. m_ObjectID = pOther->m_ObjectID;
  189. m_iElement = pOther->m_iElement;
  190. }
  191. // ---------------------------------------------------------------------------------------- //
  192. // Int property type abstraction.
  193. // ---------------------------------------------------------------------------------------- //
  194. void Int_Encode( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp, bf_write *pOut, int objectID )
  195. {
  196. int nValue = pVar->m_Int;
  197. if ( pProp->GetFlags() & SPROP_VARINT)
  198. {
  199. if ( pProp->GetFlags() & SPROP_UNSIGNED )
  200. {
  201. pOut->WriteVarInt32( nValue );
  202. }
  203. else
  204. {
  205. pOut->WriteSignedVarInt32( nValue );
  206. }
  207. }
  208. else
  209. {
  210. // If signed, preserve lower bits and then re-extend sign if nValue < 0;
  211. // if unsigned, preserve all 32 bits no matter what. Bonus: branchless.
  212. int nPreserveBits = ( 0x7FFFFFFF >> ( 32 - pProp->m_nBits ) );
  213. nPreserveBits |= ( pProp->GetFlags() & SPROP_UNSIGNED ) ? 0xFFFFFFFF : 0;
  214. int nSignExtension = ( nValue >> 31 ) & ~nPreserveBits;
  215. nValue &= nPreserveBits;
  216. nValue |= nSignExtension;
  217. #ifdef DBGFLAG_ASSERT
  218. // Assert that either the property is unsigned and in valid range,
  219. // or signed with a consistent sign extension in the high bits
  220. if ( pProp->m_nBits < 32 )
  221. {
  222. if ( pProp->GetFlags() & SPROP_UNSIGNED )
  223. {
  224. AssertMsg3( nValue == pVar->m_Int, "Unsigned prop %s needs more bits? Expected %i == %i", pProp->GetName(), nValue, pVar->m_Int );
  225. }
  226. else
  227. {
  228. AssertMsg3( nValue == pVar->m_Int, "Signed prop %s needs more bits? Expected %i == %i", pProp->GetName(), nValue, pVar->m_Int );
  229. }
  230. }
  231. else
  232. {
  233. // This should never trigger, but I'm leaving it in for old-time's sake.
  234. Assert( nValue == pVar->m_Int );
  235. }
  236. #endif
  237. pOut->WriteUBitLong( nValue, pProp->m_nBits, false );
  238. }
  239. }
  240. void Int_Decode( DecodeInfo *pInfo )
  241. {
  242. const SendProp *pProp = pInfo->m_pProp;
  243. int flags = pProp->GetFlags();
  244. if ( flags & SPROP_VARINT )
  245. {
  246. if ( flags & SPROP_UNSIGNED )
  247. {
  248. pInfo->m_Value.m_Int = (long)pInfo->m_pIn->ReadVarInt32();
  249. }
  250. else
  251. {
  252. pInfo->m_Value.m_Int = pInfo->m_pIn->ReadSignedVarInt32();
  253. }
  254. }
  255. else
  256. {
  257. int bits = pProp->m_nBits;
  258. pInfo->m_Value.m_Int = pInfo->m_pIn->ReadUBitLong(bits);
  259. if( bits != 32 && (flags & SPROP_UNSIGNED) == 0 )
  260. {
  261. unsigned long highbit = 1ul << (pProp->m_nBits - 1);
  262. if ( pInfo->m_Value.m_Int & highbit )
  263. {
  264. pInfo->m_Value.m_Int -= highbit; // strip high bit...
  265. pInfo->m_Value.m_Int -= highbit; // ... then put it back with sign extension
  266. }
  267. }
  268. }
  269. if ( pInfo->m_pRecvProp )
  270. {
  271. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  272. }
  273. }
  274. int Int_CompareDeltas( const SendProp *pProp, bf_read *p1, bf_read *p2 )
  275. {
  276. if ( pProp->GetFlags() & SPROP_VARINT)
  277. {
  278. if ( pProp->GetFlags() & SPROP_UNSIGNED )
  279. {
  280. return p1->ReadVarInt32() != p2->ReadVarInt32();
  281. }
  282. return p1->ReadSignedVarInt32() != p2->ReadSignedVarInt32();
  283. }
  284. return p1->CompareBits(p2, pProp->m_nBits);
  285. }
  286. const char* Int_GetTypeNameString()
  287. {
  288. return "DPT_Int";
  289. }
  290. bool Int_IsZero( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp )
  291. {
  292. return (pVar->m_Int == 0);
  293. }
  294. void Int_DecodeZero( DecodeInfo *pInfo )
  295. {
  296. pInfo->m_Value.m_Int = 0;
  297. if ( pInfo->m_pRecvProp )
  298. {
  299. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  300. }
  301. }
  302. bool Int_IsEncodedZero( const SendProp *pProp, bf_read *pIn )
  303. {
  304. if ( pProp->GetFlags() & SPROP_VARINT)
  305. {
  306. if ( pProp->GetFlags() & SPROP_UNSIGNED )
  307. {
  308. return pIn->ReadVarInt32() == 0;
  309. }
  310. return pIn->ReadSignedVarInt32() == 0;
  311. }
  312. return pIn->ReadUBitLong( pProp->m_nBits ) == 0;
  313. }
  314. void Int_SkipProp( const SendProp *pProp, bf_read *pIn )
  315. {
  316. if ( pProp->GetFlags() & SPROP_VARINT)
  317. {
  318. if ( pProp->GetFlags() & SPROP_UNSIGNED )
  319. {
  320. pIn->ReadVarInt32();
  321. }
  322. else
  323. {
  324. pIn->ReadSignedVarInt32();
  325. }
  326. }
  327. else
  328. {
  329. pIn->SeekRelative( pProp->m_nBits );
  330. }
  331. }
  332. // ---------------------------------------------------------------------------------------- //
  333. // Float type abstraction.
  334. // ---------------------------------------------------------------------------------------- //
  335. void Float_Encode( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp, bf_write *pOut, int objectID )
  336. {
  337. EncodeFloat( pProp, pVar->m_Float, pOut, objectID );
  338. }
  339. void Float_Decode( DecodeInfo *pInfo )
  340. {
  341. pInfo->m_Value.m_Float = DecodeFloat(pInfo->m_pProp, pInfo->m_pIn);
  342. if ( pInfo->m_pRecvProp )
  343. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  344. }
  345. int Float_CompareDeltas( const SendProp *pProp, bf_read *p1, bf_read *p2 )
  346. {
  347. int flags = pProp->GetFlags();
  348. if ( flags & SPROP_COORD )
  349. {
  350. return p1->ReadBitCoordBits() != p2->ReadBitCoordBits();
  351. }
  352. else if ( flags & ( SPROP_COORD_MP | SPROP_COORD_MP_LOWPRECISION | SPROP_COORD_MP_INTEGRAL ) )
  353. {
  354. return p1->ReadBitCoordMPBits( (flags >> 15) & 1, (flags >> 14) & 1 )
  355. != p2->ReadBitCoordMPBits( (flags >> 15) & 1, (flags >> 14) & 1 );
  356. }
  357. else
  358. {
  359. int bits;
  360. if ( flags & SPROP_NOSCALE )
  361. bits = 32;
  362. else if ( flags & SPROP_NORMAL )
  363. bits = NORMAL_FRACTIONAL_BITS+1;
  364. else
  365. bits = pProp->m_nBits;
  366. return p1->ReadUBitLong( bits ) != p2->ReadUBitLong( bits );
  367. }
  368. }
  369. const char* Float_GetTypeNameString()
  370. {
  371. return "DPT_Float";
  372. }
  373. bool Float_IsZero( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp )
  374. {
  375. return (pVar->m_Float == 0);
  376. }
  377. void Float_DecodeZero( DecodeInfo *pInfo )
  378. {
  379. pInfo->m_Value.m_Float = 0;
  380. if ( pInfo->m_pRecvProp )
  381. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  382. }
  383. bool Float_IsEncodedZero( const SendProp *pProp, bf_read *pIn )
  384. {
  385. return DecodeFloat( pProp, pIn ) == 0.0f;
  386. }
  387. void Float_SkipProp( const SendProp *pProp, bf_read *pIn )
  388. {
  389. // Check for special flags..
  390. if(pProp->GetFlags() & SPROP_COORD)
  391. {
  392. // Read the required integer and fraction flags
  393. unsigned int val = pIn->ReadUBitLong(2);
  394. // this reads two bits, the first bit (bit0 in this word) indicates integer part
  395. // the second bit (bit1 in this word) indicates the fractional part
  396. // If we got either parse them, otherwise it's a zero.
  397. if ( val )
  398. {
  399. // sign bit
  400. int seekDist = 1;
  401. // If there's an integer, read it in
  402. if ( val & 1 )
  403. seekDist += COORD_INTEGER_BITS;
  404. if ( val & 2 )
  405. seekDist += COORD_FRACTIONAL_BITS;
  406. pIn->SeekRelative( seekDist );
  407. }
  408. }
  409. else if ( pProp->GetFlags() & SPROP_COORD_MP )
  410. {
  411. pIn->ReadBitCoordMP( false, false );
  412. }
  413. else if ( pProp->GetFlags() & SPROP_COORD_MP_LOWPRECISION )
  414. {
  415. pIn->ReadBitCoordMP( false, true );
  416. }
  417. else if ( pProp->GetFlags() & SPROP_COORD_MP_INTEGRAL )
  418. {
  419. pIn->ReadBitCoordMP( true, false );
  420. }
  421. else if(pProp->GetFlags() & SPROP_NOSCALE)
  422. {
  423. pIn->SeekRelative( 32 );
  424. }
  425. else if(pProp->GetFlags() & SPROP_NORMAL)
  426. {
  427. pIn->SeekRelative( NORMAL_FRACTIONAL_BITS + 1 );
  428. }
  429. else
  430. {
  431. pIn->SeekRelative( pProp->m_nBits );
  432. }
  433. }
  434. // ---------------------------------------------------------------------------------------- //
  435. // Vector type abstraction.
  436. // ---------------------------------------------------------------------------------------- //
  437. void Vector_Encode( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp, bf_write *pOut, int objectID )
  438. {
  439. EncodeFloat(pProp, pVar->m_Vector[0], pOut, objectID);
  440. EncodeFloat(pProp, pVar->m_Vector[1], pOut, objectID);
  441. // Don't write out the third component for normals
  442. if ((pProp->GetFlags() & SPROP_NORMAL) == 0)
  443. {
  444. EncodeFloat(pProp, pVar->m_Vector[2], pOut, objectID);
  445. }
  446. else
  447. {
  448. // Write a sign bit for z instead!
  449. int signbit = (pVar->m_Vector[2] <= -NORMAL_RESOLUTION);
  450. pOut->WriteOneBit( signbit );
  451. }
  452. }
  453. void Vector_Decode(DecodeInfo *pInfo)
  454. {
  455. DecodeVector( pInfo->m_pProp, pInfo->m_pIn, pInfo->m_Value.m_Vector );
  456. if( pInfo->m_pRecvProp )
  457. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  458. }
  459. int Vector_CompareDeltas( const SendProp *pProp, bf_read *p1, bf_read *p2 )
  460. {
  461. int c1 = Float_CompareDeltas( pProp, p1, p2 );
  462. int c2 = Float_CompareDeltas( pProp, p1, p2 );
  463. int c3;
  464. if ( pProp->GetFlags() & SPROP_NORMAL )
  465. {
  466. c3 = p1->ReadOneBit() != p2->ReadOneBit();
  467. }
  468. else
  469. {
  470. c3 = Float_CompareDeltas( pProp, p1, p2 );
  471. }
  472. return c1 | c2 | c3;
  473. }
  474. const char* Vector_GetTypeNameString()
  475. {
  476. return "DPT_Vector";
  477. }
  478. bool Vector_IsZero( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp )
  479. {
  480. return ( pVar->m_Vector[0] == 0 ) && ( pVar->m_Vector[1] == 0 ) && ( pVar->m_Vector[2] == 0 );
  481. }
  482. void Vector_DecodeZero( DecodeInfo *pInfo )
  483. {
  484. pInfo->m_Value.m_Vector[0] = 0;
  485. pInfo->m_Value.m_Vector[1] = 0;
  486. pInfo->m_Value.m_Vector[2] = 0;
  487. if ( pInfo->m_pRecvProp )
  488. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  489. }
  490. bool Vector_IsEncodedZero( const SendProp *pProp, bf_read *pIn )
  491. {
  492. float v[3];
  493. DecodeVector( pProp, pIn, v );
  494. return ( v[0] == 0 ) && ( v[1] == 0 ) && ( v[2] == 0 );
  495. }
  496. void Vector_SkipProp( const SendProp *pProp, bf_read *pIn )
  497. {
  498. Float_SkipProp(pProp, pIn);
  499. Float_SkipProp(pProp, pIn);
  500. // Don't read in the third component for normals
  501. if ( pProp->GetFlags() & SPROP_NORMAL )
  502. {
  503. pIn->SeekRelative( 1 );
  504. }
  505. else
  506. {
  507. Float_SkipProp(pProp, pIn);
  508. }
  509. }
  510. // ---------------------------------------------------------------------------------------- //
  511. // VectorXY type abstraction.
  512. // ---------------------------------------------------------------------------------------- //
  513. void VectorXY_Encode( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp, bf_write *pOut, int objectID )
  514. {
  515. EncodeFloat(pProp, pVar->m_Vector[0], pOut, objectID);
  516. EncodeFloat(pProp, pVar->m_Vector[1], pOut, objectID);
  517. }
  518. void VectorXY_Decode(DecodeInfo *pInfo)
  519. {
  520. pInfo->m_Value.m_Vector[0] = DecodeFloat(pInfo->m_pProp, pInfo->m_pIn);
  521. pInfo->m_Value.m_Vector[1] = DecodeFloat(pInfo->m_pProp, pInfo->m_pIn);
  522. if( pInfo->m_pRecvProp )
  523. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  524. }
  525. int VectorXY_CompareDeltas( const SendProp *pProp, bf_read *p1, bf_read *p2 )
  526. {
  527. int c1 = Float_CompareDeltas( pProp, p1, p2 );
  528. int c2 = Float_CompareDeltas( pProp, p1, p2 );
  529. return c1 | c2;
  530. }
  531. const char* VectorXY_GetTypeNameString()
  532. {
  533. return "DPT_VectorXY";
  534. }
  535. bool VectorXY_IsZero( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp )
  536. {
  537. return ( pVar->m_Vector[0] == 0 ) && ( pVar->m_Vector[1] == 0 );
  538. }
  539. void VectorXY_DecodeZero( DecodeInfo *pInfo )
  540. {
  541. pInfo->m_Value.m_Vector[0] = 0;
  542. pInfo->m_Value.m_Vector[1] = 0;
  543. if ( pInfo->m_pRecvProp )
  544. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  545. }
  546. bool VectorXY_IsEncodedZero( const SendProp *pProp, bf_read *pIn )
  547. {
  548. float v[2];
  549. v[0] = DecodeFloat(pProp, pIn);
  550. v[1] = DecodeFloat(pProp, pIn);
  551. return ( v[0] == 0 ) && ( v[1] == 0 );
  552. }
  553. void VectorXY_SkipProp( const SendProp *pProp, bf_read *pIn )
  554. {
  555. Float_SkipProp(pProp, pIn);
  556. Float_SkipProp(pProp, pIn);
  557. }
  558. #if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!!
  559. // ---------------------------------------------------------------------------------------- //
  560. // Quaternion type abstraction.
  561. // ---------------------------------------------------------------------------------------- //
  562. void Quaternion_Encode( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp, bf_write *pOut, int objectID )
  563. {
  564. EncodeFloat(pProp, pVar->m_Vector[0], pOut, objectID);
  565. EncodeFloat(pProp, pVar->m_Vector[1], pOut, objectID);
  566. EncodeFloat(pProp, pVar->m_Vector[2], pOut, objectID);
  567. EncodeFloat(pProp, pVar->m_Vector[3], pOut, objectID);
  568. }
  569. void Quaternion_Decode(DecodeInfo *pInfo)
  570. {
  571. DecodeQuaternion( pInfo->m_pProp, pInfo->m_pIn, pInfo->m_Value.m_Vector );
  572. if( pInfo->m_pRecvProp )
  573. {
  574. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  575. }
  576. }
  577. int Quaternion_CompareDeltas( const SendProp *pProp, bf_read *p1, bf_read *p2 )
  578. {
  579. int c1 = Float_CompareDeltas( pProp, p1, p2 );
  580. int c2 = Float_CompareDeltas( pProp, p1, p2 );
  581. int c3 = Float_CompareDeltas( pProp, p1, p2 );
  582. int c4 = Float_CompareDeltas( pProp, p1, p2 );
  583. return c1 | c2 | c3 | c4;
  584. }
  585. const char* Quaternion_GetTypeNameString()
  586. {
  587. return "DPT_Quaternion";
  588. }
  589. bool Quaternion_IsZero( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp )
  590. {
  591. return ( pVar->m_Vector[0] == 0 ) && ( pVar->m_Vector[1] == 0 ) && ( pVar->m_Vector[2] == 0 ) && ( pVar->m_Vector[3] == 0 );
  592. }
  593. void Quaternion_DecodeZero( DecodeInfo *pInfo )
  594. {
  595. pInfo->m_Value.m_Vector[0] = 0;
  596. pInfo->m_Value.m_Vector[1] = 0;
  597. pInfo->m_Value.m_Vector[2] = 0;
  598. pInfo->m_Value.m_Vector[3] = 0;
  599. if ( pInfo->m_pRecvProp )
  600. {
  601. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  602. }
  603. }
  604. bool Quaternion_IsEncodedZero( const SendProp *pProp, bf_read *pIn )
  605. {
  606. float v[4];
  607. DecodeQuaternion( pProp, pIn, v );
  608. return ( v[0] == 0 ) && ( v[1] == 0 ) && ( v[2] == 0 ) && ( v[3] == 0 );
  609. }
  610. void Quaternion_SkipProp( const SendProp *pProp, bf_read *pIn )
  611. {
  612. Float_SkipProp(pProp, pIn);
  613. Float_SkipProp(pProp, pIn);
  614. Float_SkipProp(pProp, pIn);
  615. Float_SkipProp(pProp, pIn);
  616. }
  617. #endif
  618. // ---------------------------------------------------------------------------------------- //
  619. // String type abstraction.
  620. // ---------------------------------------------------------------------------------------- //
  621. void String_Encode( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp, bf_write *pOut, int objectID )
  622. {
  623. // First count the string length, then do one WriteBits call.
  624. int len;
  625. for ( len=0; len < DT_MAX_STRING_BUFFERSIZE-1; len++ )
  626. {
  627. if( pVar->m_pString[len] == 0 )
  628. {
  629. break;
  630. }
  631. }
  632. // Optionally write the length here so deltas can be compared faster.
  633. pOut->WriteUBitLong( len, DT_MAX_STRING_BITS );
  634. pOut->WriteBits( pVar->m_pString, len * 8 );
  635. }
  636. void String_Decode(DecodeInfo *pInfo)
  637. {
  638. // Read it in.
  639. int len = pInfo->m_pIn->ReadUBitLong( DT_MAX_STRING_BITS );
  640. char *tempStr = pInfo->m_TempStr;
  641. if ( len >= DT_MAX_STRING_BUFFERSIZE )
  642. {
  643. Warning( "String_Decode( %s ) invalid length (%d)\n", pInfo->m_pRecvProp->GetName(), len );
  644. len = DT_MAX_STRING_BUFFERSIZE - 1;
  645. }
  646. pInfo->m_pIn->ReadBits( tempStr, len*8 );
  647. tempStr[len] = 0;
  648. pInfo->m_Value.m_pString = tempStr;
  649. // Give it to the RecvProxy.
  650. if ( pInfo->m_pRecvProp )
  651. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  652. }
  653. // Compare the bits in pBuf1 and pBuf2 and return 1 if they are different.
  654. // This must always seek both buffers to wherever they start at + nBits.
  655. static inline int AreBitsDifferent( bf_read *pBuf1, bf_read *pBuf2, int nBits )
  656. {
  657. int nDWords = nBits >> 5;
  658. int diff = 0;
  659. for ( int iDWord=0; iDWord < nDWords; iDWord++ )
  660. {
  661. diff |= (pBuf1->ReadUBitLong(32) != pBuf2->ReadUBitLong(32));
  662. }
  663. int nRemainingBits = nBits - (nDWords<<5);
  664. if (nRemainingBits > 0)
  665. diff |= pBuf1->ReadUBitLong( nRemainingBits ) != pBuf2->ReadUBitLong( nRemainingBits );
  666. return diff;
  667. }
  668. int String_CompareDeltas( const SendProp *pProp, bf_read *p1, bf_read *p2 )
  669. {
  670. int len1 = p1->ReadUBitLong( DT_MAX_STRING_BITS );
  671. int len2 = p2->ReadUBitLong( DT_MAX_STRING_BITS );
  672. if ( len1 == len2 )
  673. {
  674. // check if both strings are empty
  675. if (len1 == 0)
  676. return false;
  677. // Ok, they're short and fast.
  678. return AreBitsDifferent( p1, p2, len1*8 );
  679. }
  680. else
  681. {
  682. p1->SeekRelative( len1 * 8 );
  683. p2->SeekRelative( len2 * 8 );
  684. return true;
  685. }
  686. }
  687. const char* String_GetTypeNameString()
  688. {
  689. return "DPT_String";
  690. }
  691. bool String_IsZero( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp )
  692. {
  693. return ( pVar->m_pString[0] == 0 );
  694. }
  695. void String_DecodeZero( DecodeInfo *pInfo )
  696. {
  697. pInfo->m_Value.m_pString = pInfo->m_TempStr;
  698. pInfo->m_TempStr[0] = 0;
  699. if ( pInfo->m_pRecvProp )
  700. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  701. }
  702. bool String_IsEncodedZero( const SendProp *pProp, bf_read *pIn )
  703. {
  704. // Read it in.
  705. int len = pIn->ReadUBitLong( DT_MAX_STRING_BITS );
  706. pIn->SeekRelative( len*8 );
  707. return len == 0;
  708. }
  709. void String_SkipProp( const SendProp *pProp, bf_read *pIn )
  710. {
  711. int len = pIn->ReadUBitLong( DT_MAX_STRING_BITS );
  712. pIn->SeekRelative( len*8 );
  713. }
  714. // ---------------------------------------------------------------------------------------- //
  715. // Array abstraction.
  716. // ---------------------------------------------------------------------------------------- //
  717. int Array_GetLength( const unsigned char *pStruct, const SendProp *pProp, int objectID )
  718. {
  719. // Get the array length from the proxy.
  720. ArrayLengthSendProxyFn proxy = pProp->GetArrayLengthProxy();
  721. if ( proxy )
  722. {
  723. int nElements = proxy( pStruct, objectID );
  724. // Make sure it's not too big.
  725. if ( nElements > pProp->GetNumElements() )
  726. {
  727. Assert( false );
  728. nElements = pProp->GetNumElements();
  729. }
  730. return nElements;
  731. }
  732. else
  733. {
  734. return pProp->GetNumElements();
  735. }
  736. }
  737. void Array_Encode( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp, bf_write *pOut, int objectID )
  738. {
  739. SendProp *pArrayProp = pProp->GetArrayProp();
  740. AssertMsg( pArrayProp, "Array_Encode: missing m_pArrayProp for SendProp '%s'.", pProp->m_pVarName );
  741. int nElements = Array_GetLength( pStruct, pProp, objectID );
  742. // Write the number of elements.
  743. pOut->WriteUBitLong( nElements, pProp->GetNumArrayLengthBits() );
  744. unsigned char *pCurStructOffset = (unsigned char*)pStruct + pArrayProp->GetOffset();
  745. for ( int iElement=0; iElement < nElements; iElement++ )
  746. {
  747. DVariant var;
  748. // Call the proxy to get the value, then encode.
  749. pArrayProp->GetProxyFn()( pArrayProp, pStruct, pCurStructOffset, &var, iElement, objectID );
  750. g_PropTypeFns[pArrayProp->GetType()].Encode( pStruct, &var, pArrayProp, pOut, objectID );
  751. pCurStructOffset += pProp->GetElementStride();
  752. }
  753. }
  754. void Array_Decode( DecodeInfo *pInfo )
  755. {
  756. SendProp *pArrayProp = pInfo->m_pProp->GetArrayProp();
  757. AssertMsg( pArrayProp, ("Array_Decode: missing m_pArrayProp for a property.") );
  758. // Setup a DecodeInfo that is used to decode each of the child properties.
  759. DecodeInfo subDecodeInfo;
  760. subDecodeInfo.CopyVars( pInfo );
  761. subDecodeInfo.m_pProp = pArrayProp;
  762. int elementStride = 0;
  763. ArrayLengthRecvProxyFn lengthProxy = 0;
  764. if ( pInfo->m_pRecvProp )
  765. {
  766. RecvProp *pArrayRecvProp = pInfo->m_pRecvProp->GetArrayProp();
  767. subDecodeInfo.m_pRecvProp = pArrayRecvProp;
  768. // Note we get the OFFSET from the array element property and the STRIDE from the array itself.
  769. subDecodeInfo.m_pData = (char*)pInfo->m_pData + pArrayRecvProp->GetOffset();
  770. elementStride = pInfo->m_pRecvProp->GetElementStride();
  771. Assert( elementStride != -1 ); // (Make sure it was set..)
  772. lengthProxy = pInfo->m_pRecvProp->GetArrayLengthProxy();
  773. }
  774. int nElements = pInfo->m_pIn->ReadUBitLong( pInfo->m_pProp->GetNumArrayLengthBits() );
  775. if ( lengthProxy )
  776. lengthProxy( pInfo->m_pStruct, pInfo->m_ObjectID, nElements );
  777. for ( subDecodeInfo.m_iElement=0; subDecodeInfo.m_iElement < nElements; subDecodeInfo.m_iElement++ )
  778. {
  779. g_PropTypeFns[pArrayProp->GetType()].Decode( &subDecodeInfo );
  780. subDecodeInfo.m_pData = (char*)subDecodeInfo.m_pData + elementStride;
  781. }
  782. }
  783. int Array_CompareDeltas( const SendProp *pProp, bf_read *p1, bf_read *p2 )
  784. {
  785. SendProp *pArrayProp = pProp->GetArrayProp();
  786. AssertMsg( pArrayProp, "Array_CompareDeltas: missing m_pArrayProp for SendProp '%s'.", pProp->m_pVarName );
  787. int nLengthBits = pProp->GetNumArrayLengthBits();
  788. int length1 = p1->ReadUBitLong( nLengthBits );
  789. int length2 = p2->ReadUBitLong( nLengthBits );
  790. int bDifferent = length1 != length2;
  791. // Compare deltas on the props that are the same.
  792. int nSame = min( length1, length2 );
  793. for ( int iElement=0; iElement < nSame; iElement++ )
  794. {
  795. bDifferent |= g_PropTypeFns[pArrayProp->GetType()].CompareDeltas( pArrayProp, p1, p2 );
  796. }
  797. // Now just eat up the remaining properties in whichever buffer was larger.
  798. if ( length1 != length2 )
  799. {
  800. bf_read *buffer = (length1 > length2) ? p1 : p2;
  801. int nExtra = max( length1, length2 ) - nSame;
  802. for ( int iEatUp=0; iEatUp < nExtra; iEatUp++ )
  803. {
  804. SkipPropData( buffer, pArrayProp );
  805. }
  806. }
  807. return bDifferent;
  808. }
  809. void Array_FastCopy(
  810. const SendProp *pSendProp,
  811. const RecvProp *pRecvProp,
  812. const unsigned char *pSendData,
  813. unsigned char *pRecvData,
  814. int objectID )
  815. {
  816. const RecvProp *pArrayRecvProp = pRecvProp->GetArrayProp();
  817. const SendProp *pArraySendProp = pSendProp->GetArrayProp();
  818. CRecvProxyData recvProxyData;
  819. recvProxyData.m_pRecvProp = pArrayRecvProp;
  820. recvProxyData.m_ObjectID = objectID;
  821. // Find out the array length and call the RecvProp's array-length proxy.
  822. int nElements = Array_GetLength( pSendData, pSendProp, objectID );
  823. ArrayLengthRecvProxyFn lengthProxy = pRecvProp->GetArrayLengthProxy();
  824. if ( lengthProxy )
  825. lengthProxy( pRecvData, objectID, nElements );
  826. const unsigned char *pCurSendPos = pSendData + pArraySendProp->GetOffset();
  827. unsigned char *pCurRecvPos = pRecvData + pArrayRecvProp->GetOffset();
  828. for ( recvProxyData.m_iElement=0; recvProxyData.m_iElement < nElements; recvProxyData.m_iElement++ )
  829. {
  830. // Get this array element out of the sender's data.
  831. pArraySendProp->GetProxyFn()( pArraySendProp, pSendData, pCurSendPos, &recvProxyData.m_Value, recvProxyData.m_iElement, objectID );
  832. pCurSendPos += pSendProp->GetElementStride();
  833. // Write it into the receiver.
  834. pArrayRecvProp->GetProxyFn()( &recvProxyData, pRecvData, pCurRecvPos );
  835. pCurRecvPos += pRecvProp->GetElementStride();
  836. }
  837. }
  838. const char* Array_GetTypeNameString()
  839. {
  840. return "DPT_Array";
  841. }
  842. bool Array_IsZero( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp )
  843. {
  844. int nElements = Array_GetLength( pStruct, pProp, -1 );
  845. return ( nElements == 0 );
  846. }
  847. void Array_DecodeZero( DecodeInfo *pInfo )
  848. {
  849. ArrayLengthRecvProxyFn lengthProxy = pInfo->m_pRecvProp->GetArrayLengthProxy();
  850. if ( lengthProxy )
  851. lengthProxy( pInfo->m_pStruct, pInfo->m_ObjectID, 0 );
  852. }
  853. bool Array_IsEncodedZero( const SendProp *pProp, bf_read *pIn )
  854. {
  855. SendProp *pArrayProp = pProp->GetArrayProp();
  856. AssertMsg( pArrayProp, ("Array_IsEncodedZero: missing m_pArrayProp for a property.") );
  857. int nElements = pIn->ReadUBitLong( pProp->GetNumArrayLengthBits() );
  858. for ( int i=0; i < nElements; i++ )
  859. {
  860. // skip over data
  861. g_PropTypeFns[pArrayProp->GetType()].IsEncodedZero( pArrayProp, pIn );
  862. }
  863. return nElements == 0;;
  864. }
  865. void Array_SkipProp( const SendProp *pProp, bf_read *pIn )
  866. {
  867. SendProp *pArrayProp = pProp->GetArrayProp();
  868. AssertMsg( pArrayProp, ("Array_SkipProp: missing m_pArrayProp for a property.") );
  869. int nElements = pIn->ReadUBitLong( pProp->GetNumArrayLengthBits() );
  870. for ( int i=0; i < nElements; i++ )
  871. {
  872. // skip over data
  873. g_PropTypeFns[pArrayProp->GetType()].SkipProp( pArrayProp, pIn );
  874. }
  875. }
  876. // ---------------------------------------------------------------------------------------- //
  877. // Datatable type abstraction.
  878. // ---------------------------------------------------------------------------------------- //
  879. const char* DataTable_GetTypeNameString()
  880. {
  881. return "DPT_DataTable";
  882. }
  883. // ---------------------------------------------------------------------------------------- //
  884. // Int 64 property type abstraction.
  885. // ---------------------------------------------------------------------------------------- //
  886. void Int64_Encode( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp, bf_write *pOut, int objectID )
  887. {
  888. #ifdef SUPPORTS_INT64
  889. if ( pProp->GetFlags() & SPROP_VARINT)
  890. {
  891. if ( pProp->GetFlags() & SPROP_UNSIGNED )
  892. {
  893. pOut->WriteVarInt64( pVar->m_Int64 );
  894. }
  895. else
  896. {
  897. pOut->WriteSignedVarInt32( pVar->m_Int64 );
  898. }
  899. }
  900. else
  901. {
  902. bool bNeg = pVar->m_Int64 < 0;
  903. int64 iCopy = bNeg ? -pVar->m_Int64 : pVar->m_Int64;
  904. uint32 *pInt = (uint32*)&iCopy;
  905. uint32 lowInt = *pInt++;
  906. uint32 highInt = *pInt;
  907. if( pProp->IsSigned() )
  908. {
  909. pOut->WriteOneBit( bNeg );
  910. pOut->WriteUBitLong( (unsigned int)lowInt, 32 );
  911. pOut->WriteUBitLong( (unsigned int)highInt, pProp->m_nBits - 32 - 1 ); // For the sign bit
  912. }
  913. else
  914. {
  915. pOut->WriteUBitLong( (unsigned int)lowInt, 32 );
  916. pOut->WriteUBitLong( (unsigned int)highInt, pProp->m_nBits - 32 );
  917. }
  918. }
  919. #endif
  920. }
  921. void Int64_Decode( DecodeInfo *pInfo )
  922. {
  923. #ifdef SUPPORTS_INT64
  924. if ( pInfo->m_pProp->GetFlags() & SPROP_VARINT )
  925. {
  926. if ( pInfo->m_pProp->GetFlags() & SPROP_UNSIGNED )
  927. {
  928. pInfo->m_Value.m_Int64 = (int64)pInfo->m_pIn->ReadVarInt64();
  929. }
  930. else
  931. {
  932. pInfo->m_Value.m_Int64 = pInfo->m_pIn->ReadSignedVarInt64();
  933. }
  934. }
  935. else
  936. {
  937. uint32 highInt = 0;
  938. uint32 lowInt = 0;
  939. bool bNeg = false;
  940. if(pInfo->m_pProp->IsSigned())
  941. {
  942. bNeg = pInfo->m_pIn->ReadOneBit() != 0;
  943. lowInt = pInfo->m_pIn->ReadUBitLong( 32 );
  944. highInt = pInfo->m_pIn->ReadUBitLong( pInfo->m_pProp->m_nBits - 32 - 1 );
  945. }
  946. else
  947. {
  948. lowInt = pInfo->m_pIn->ReadUBitLong( 32 );
  949. highInt = pInfo->m_pIn->ReadUBitLong( pInfo->m_pProp->m_nBits - 32 );
  950. }
  951. uint32 *pInt = (uint32*)&pInfo->m_Value.m_Int64;
  952. *pInt++ = lowInt;
  953. *pInt = highInt;
  954. if ( bNeg )
  955. {
  956. pInfo->m_Value.m_Int64 = -pInfo->m_Value.m_Int64;
  957. }
  958. }
  959. if ( pInfo->m_pRecvProp )
  960. {
  961. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  962. }
  963. #endif
  964. }
  965. int Int64_CompareDeltas( const SendProp *pProp, bf_read *p1, bf_read *p2 )
  966. {
  967. if ( pProp->GetFlags() & SPROP_VARINT)
  968. {
  969. if ( pProp->GetFlags() & SPROP_UNSIGNED )
  970. {
  971. return p1->ReadVarInt64() != p2->ReadVarInt64();
  972. }
  973. return p1->ReadSignedVarInt64() != p2->ReadSignedVarInt64();
  974. }
  975. uint32 highInt1 = p1->ReadUBitLong( pProp->m_nBits - 32 );
  976. uint32 lowInt1 = p1->ReadUBitLong( 32 );
  977. uint32 highInt2 = p2->ReadUBitLong( pProp->m_nBits - 32 );
  978. uint32 lowInt2 = p2->ReadUBitLong( 32 );
  979. return highInt1 != highInt2 || lowInt1 != lowInt2;
  980. }
  981. const char* Int64_GetTypeNameString()
  982. {
  983. return "DPT_Int64";
  984. }
  985. bool Int64_IsZero( const unsigned char *pStruct, DVariant *pVar, const SendProp *pProp )
  986. {
  987. #ifdef SUPPORTS_INT64
  988. return (pVar->m_Int64 == 0);
  989. #else
  990. return false;
  991. #endif
  992. }
  993. void Int64_DecodeZero( DecodeInfo *pInfo )
  994. {
  995. #ifdef SUPPORTS_INT64
  996. pInfo->m_Value.m_Int64 = 0;
  997. if ( pInfo->m_pRecvProp )
  998. {
  999. pInfo->m_pRecvProp->GetProxyFn()( pInfo, pInfo->m_pStruct, pInfo->m_pData );
  1000. }
  1001. #endif
  1002. }
  1003. bool Int64_IsEncodedZero( const SendProp *pProp, bf_read *pIn )
  1004. {
  1005. if ( pProp->GetFlags() & SPROP_VARINT)
  1006. {
  1007. if ( pProp->GetFlags() & SPROP_UNSIGNED )
  1008. {
  1009. return pIn->ReadVarInt64() == 0;
  1010. }
  1011. return pIn->ReadSignedVarInt64() == 0;
  1012. }
  1013. uint32 highInt1 = pIn->ReadUBitLong( pProp->m_nBits - 32 );
  1014. uint32 lowInt1 = pIn->ReadUBitLong( 32 );
  1015. return (highInt1 == 0 && lowInt1 == 0);
  1016. }
  1017. void Int64_SkipProp( const SendProp *pProp, bf_read *pIn )
  1018. {
  1019. if ( pProp->GetFlags() & SPROP_VARINT)
  1020. {
  1021. if ( pProp->GetFlags() & SPROP_UNSIGNED )
  1022. {
  1023. pIn->ReadVarInt64();
  1024. }
  1025. else
  1026. {
  1027. pIn->ReadSignedVarInt64();
  1028. }
  1029. }
  1030. else
  1031. {
  1032. pIn->SeekRelative( pProp->m_nBits );
  1033. }
  1034. }
  1035. PropTypeFns g_PropTypeFns[DPT_NUMSendPropTypes] =
  1036. {
  1037. // DPT_Int
  1038. {
  1039. Int_Encode,
  1040. Int_Decode,
  1041. Int_CompareDeltas,
  1042. Generic_FastCopy,
  1043. Int_GetTypeNameString,
  1044. Int_IsZero,
  1045. Int_DecodeZero,
  1046. Int_IsEncodedZero,
  1047. Int_SkipProp,
  1048. },
  1049. // DPT_Float
  1050. {
  1051. Float_Encode,
  1052. Float_Decode,
  1053. Float_CompareDeltas,
  1054. Generic_FastCopy,
  1055. Float_GetTypeNameString,
  1056. Float_IsZero,
  1057. Float_DecodeZero,
  1058. Float_IsEncodedZero,
  1059. Float_SkipProp,
  1060. },
  1061. // DPT_Vector
  1062. {
  1063. Vector_Encode,
  1064. Vector_Decode,
  1065. Vector_CompareDeltas,
  1066. Generic_FastCopy,
  1067. Vector_GetTypeNameString,
  1068. Vector_IsZero,
  1069. Vector_DecodeZero,
  1070. Vector_IsEncodedZero,
  1071. Vector_SkipProp,
  1072. },
  1073. // DPT_VectorXY
  1074. {
  1075. VectorXY_Encode,
  1076. VectorXY_Decode,
  1077. VectorXY_CompareDeltas,
  1078. Generic_FastCopy,
  1079. VectorXY_GetTypeNameString,
  1080. VectorXY_IsZero,
  1081. VectorXY_DecodeZero,
  1082. VectorXY_IsEncodedZero,
  1083. VectorXY_SkipProp,
  1084. },
  1085. // DPT_String
  1086. {
  1087. String_Encode,
  1088. String_Decode,
  1089. String_CompareDeltas,
  1090. Generic_FastCopy,
  1091. String_GetTypeNameString,
  1092. String_IsZero,
  1093. String_DecodeZero,
  1094. String_IsEncodedZero,
  1095. String_SkipProp,
  1096. },
  1097. // DPT_Array
  1098. {
  1099. Array_Encode,
  1100. Array_Decode,
  1101. Array_CompareDeltas,
  1102. Array_FastCopy,
  1103. Array_GetTypeNameString,
  1104. Array_IsZero,
  1105. Array_DecodeZero,
  1106. Array_IsEncodedZero,
  1107. Array_SkipProp,
  1108. },
  1109. // DPT_DataTable
  1110. {
  1111. NULL,
  1112. NULL,
  1113. NULL,
  1114. NULL,
  1115. DataTable_GetTypeNameString,
  1116. NULL,
  1117. NULL,
  1118. NULL,
  1119. NULL,
  1120. },
  1121. #if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!!
  1122. // DPT_Quaternion
  1123. {
  1124. Quaternion_Encode,
  1125. Quaternion_Decode,
  1126. Quaternion_CompareDeltas,
  1127. Generic_FastCopy,
  1128. Quaternion_GetTypeNameString,
  1129. Quaternion_IsZero,
  1130. Quaternion_DecodeZero,
  1131. Quaternion_IsEncodedZero,
  1132. Quaternion_SkipProp,
  1133. },
  1134. #endif
  1135. #ifdef SUPPORTS_INT64
  1136. // DPT_Int64
  1137. {
  1138. Int64_Encode,
  1139. Int64_Decode,
  1140. Int64_CompareDeltas,
  1141. Generic_FastCopy,
  1142. Int64_GetTypeNameString,
  1143. Int64_IsZero,
  1144. Int64_DecodeZero,
  1145. Int64_IsEncodedZero,
  1146. Int64_SkipProp,
  1147. },
  1148. #endif
  1149. };