From 8b76ab93fb8bb0ec43815839e2fe38d99df6024d Mon Sep 17 00:00:00 2001 From: SNMetamorph <25657591+SNMetamorph@users.noreply.github.com> Date: Thu, 8 Jul 2021 15:32:35 +0400 Subject: [PATCH] engine: net_encode: made delta more GoldSrc consistant --- engine/common/net_encode.c | 123 +++++++++++++++++++++++-------------- engine/common/net_encode.h | 14 ++--- 2 files changed, 84 insertions(+), 53 deletions(-) diff --git a/engine/common/net_encode.c b/engine/common/net_encode.c index 084b6e8b..ac1777fe 100644 --- a/engine/common/net_encode.c +++ b/engine/common/net_encode.c @@ -473,13 +473,13 @@ qboolean Delta_AddField( const char *pStructName, const char *pName, int flags, void Delta_WriteTableField( sizebuf_t *msg, int tableIndex, const delta_t *pField ) { - int nameIndex; - delta_info_t *dt; + int nameIndex; + delta_info_t *dt; Assert( pField != NULL ); if( !COM_CheckString( pField->name )) - return; // not initialized ? + return;// not initialized ? dt = Delta_FindStructByIndex( tableIndex ); Assert( dt && dt->bInitialized ); @@ -488,20 +488,20 @@ void Delta_WriteTableField( sizebuf_t *msg, int tableIndex, const delta_t *pFiel Assert( nameIndex >= 0 && nameIndex < dt->maxFields ); MSG_BeginServerCmd( msg, svc_deltatable ); - MSG_WriteUBitLong( msg, tableIndex, 4 ); // assume we support 16 network tables - MSG_WriteUBitLong( msg, nameIndex, 8 ); // 255 fields by struct should be enough - MSG_WriteUBitLong( msg, pField->flags, 10 ); // flags are indicated various input types - MSG_WriteUBitLong( msg, pField->bits - 1, 5 ); // max received value is 32 (32 bit) + MSG_WriteUBitLong( msg, tableIndex, 4 ); // assume we support 16 network tables + MSG_WriteUBitLong( msg, nameIndex, 8 ); // 255 fields by struct should be enough + MSG_WriteUBitLong( msg, pField->flags, 10 ); // flags are indicated various input types + MSG_WriteUBitLong( msg, pField->bits - 1, 5 ); // max received value is 32 (32 bit) // multipliers is null-compressed - if( pField->multiplier != 1.0f ) + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) { MSG_WriteOneBit( msg, 1 ); MSG_WriteFloat( msg, pField->multiplier ); } else MSG_WriteOneBit( msg, 0 ); - if( pField->post_multiplier != 1.0f ) + if( pField->post_multiplier <= 0.9999f || pField->post_multiplier >= 1.0001f ) { MSG_WriteOneBit( msg, 1 ); MSG_WriteFloat( msg, pField->post_multiplier ); @@ -898,7 +898,7 @@ int Delta_ClampIntegerField( delta_t *pField, int iValue, qboolean bSigned, int { #ifdef _DEBUG if( numbits < 32 && abs( iValue ) >= (uint)BIT( numbits )) - Con_Reportf( "%s %d overflow %d\n", pField->name, abs( iValue ), (uint)BIT( numbits )); + Con_Reportf( S_WARN "Delta_ClampIntegerField: field %s = %d overflowed %d\n", pField->name, abs( iValue ), (uint)BIT( numbits )); #endif if( numbits < 32 ) { @@ -919,7 +919,7 @@ compare fields by offsets assume from and to is valid ===================== */ -qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timebase ) +qboolean Delta_CompareField( delta_t *pField, void *from, void *to, double timebase ) { qboolean bSigned = ( pField->flags & DT_SIGNED ) ? true : false; float val_a, val_b; @@ -949,8 +949,12 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits ); toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits ); - if( pField->multiplier != 1.0f ) fromF *= pField->multiplier; - if( pField->multiplier != 1.0f ) toF *= pField->multiplier; + + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) + fromF *= pField->multiplier; + + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) + toF *= pField->multiplier; } else if( pField->flags & DT_SHORT ) { @@ -967,8 +971,12 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits ); toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits ); - if( pField->multiplier != 1.0f ) fromF *= pField->multiplier; - if( pField->multiplier != 1.0f ) toF *= pField->multiplier; + + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) + fromF *= pField->multiplier; + + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) + toF *= pField->multiplier; } else if( pField->flags & DT_INTEGER ) { @@ -991,8 +999,10 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba #endif fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits ); toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits ); - if( pField->multiplier != 1.0f ) fromF *= pField->multiplier; - if( pField->multiplier != 1.0f ) toF *= pField->multiplier; + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) + fromF *= pField->multiplier; + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) + toF *= pField->multiplier; } else if( pField->flags & ( DT_ANGLE|DT_FLOAT )) { @@ -1002,10 +1012,10 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba } else if( pField->flags & DT_TIMEWINDOW_8 ) { - val_a = Q_rint((*(float *)((byte *)from + pField->offset )) * 100.0f ); - val_b = Q_rint((*(float *)((byte *)to + pField->offset )) * 100.0f ); - val_a -= Q_rint(timebase * 100.0f); - val_b -= Q_rint(timebase * 100.0f); + val_a = Q_rint((*(float *)((byte *)from + pField->offset )) * 100.0 ); + val_b = Q_rint((*(float *)((byte *)to + pField->offset )) * 100.0 ); + val_a -= Q_rint(timebase * 100.0); + val_b -= Q_rint(timebase * 100.0); fromF = *((int *)&val_a); toF = *((int *)&val_b); } @@ -1014,7 +1024,7 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba val_a = (*(float *)((byte *)from + pField->offset )); val_b = (*(float *)((byte *)to + pField->offset )); - if( pField->multiplier != 1.0f ) + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) { val_a *= pField->multiplier; val_b *= pField->multiplier; @@ -1050,7 +1060,7 @@ Delta_TestBaseline compare baselines to find optimal ===================== */ -int Delta_TestBaseline( entity_state_t *from, entity_state_t *to, qboolean player, float timebase ) +int Delta_TestBaseline( entity_state_t *from, entity_state_t *to, qboolean player, double timebase ) { delta_info_t *dt = NULL; delta_t *pField; @@ -1108,9 +1118,9 @@ write fields by offsets assume from and to is valid ===================== */ -qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to, float timebase ) +qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to, double timebase ) { - qboolean bSigned = ( pField->flags & DT_SIGNED ) ? true : false; + qboolean bSigned = ( pField->flags & DT_SIGNED ) ? true : false; float flValue, flAngle, flTime; uint iValue; const char *pStr; @@ -1130,7 +1140,10 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to else iValue = *(uint8_t *)((int8_t *)to + pField->offset ); iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits ); - if( pField->multiplier != 1.0f ) iValue *= pField->multiplier; + + if( pField->multiplier < 0.9999f || pField->multiplier > 1.0001f ) + iValue *= pField->multiplier; + MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); } else if( pField->flags & DT_SHORT ) @@ -1140,7 +1153,10 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to else iValue = *(uint16_t *)((int8_t *)to + pField->offset ); iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits ); - if( pField->multiplier != 1.0f ) iValue *= pField->multiplier; + + if( pField->multiplier < 0.9999f || pField->multiplier > 1.0001f ) + iValue *= pField->multiplier; + MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); } else if( pField->flags & DT_INTEGER ) @@ -1157,13 +1173,16 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to #pragma GCC diagnostic pop #endif iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits ); - if( pField->multiplier != 1.0f ) iValue *= pField->multiplier; + + if( pField->multiplier < 0.9999f || pField->multiplier > 1.0001f ) + iValue *= pField->multiplier; + MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); } else if( pField->flags & DT_FLOAT ) { flValue = *(float *)((byte *)to + pField->offset ); - iValue = (int)(flValue * pField->multiplier); + iValue = (int)((double)flValue * pField->multiplier); iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); } @@ -1179,7 +1198,7 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to { bSigned = true; // timewindow is always signed flValue = *(float *)((byte *)to + pField->offset ); - iValue = (int)Q_rint( timebase * 100.0f ) - (int)Q_rint( flValue * 100.0f ); + iValue = (int)Q_rint( timebase * 100.0 ) - (int)Q_rint( flValue * 100.0 ); iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); } @@ -1207,7 +1226,7 @@ read fields by offsets assume 'from' and 'to' is valid ===================== */ -qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to, float timebase ) +qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to, double timebase ) { qboolean bSigned = ( pField->flags & DT_SIGNED ) ? true : false; float flValue, flAngle, flTime; @@ -1225,7 +1244,8 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to, if( bChanged ) { iValue = MSG_ReadBitLong( msg, pField->bits, bSigned ); - if( pField->multiplier != 1.0f ) iValue /= pField->multiplier; + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) + iValue /= pField->multiplier; } else { @@ -1244,7 +1264,8 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to, if( bChanged ) { iValue = MSG_ReadBitLong( msg, pField->bits, bSigned ); - if( pField->multiplier != 1.0f ) iValue /= pField->multiplier; + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) + iValue /= pField->multiplier; } else { @@ -1267,7 +1288,8 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to, if( bChanged ) { iValue = MSG_ReadBitLong( msg, pField->bits, bSigned ); - if( pField->multiplier != 1.0f ) iValue /= pField->multiplier; + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) + iValue /= pField->multiplier; } else { @@ -1289,8 +1311,16 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to, if( bChanged ) { iValue = MSG_ReadBitLong( msg, pField->bits, bSigned ); - flValue = (int)iValue * ( 1.0f / pField->multiplier ); - flValue = flValue * pField->post_multiplier; + if( bSigned ) + flValue = (int)iValue; + else + flValue = iValue; + + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) + flValue = flValue / pField->multiplier; + + if( pField->post_multiplier <= 0.9999f || pField->post_multiplier >= 1.0001f) + flValue = flValue * pField->post_multiplier; } else { @@ -1316,7 +1346,7 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to, { bSigned = true; // timewindow is always signed iValue = MSG_ReadBitLong( msg, pField->bits, bSigned ); - flTime = ((timebase * 100.0f) - iValue ) / 100.0f; + flTime = (timebase * 100.0 - iValue) / 100.0; } else { @@ -1330,10 +1360,11 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to, { bSigned = true; // timewindow is always signed iValue = MSG_ReadBitLong( msg, pField->bits, bSigned ); - flTime = ((timebase * pField->multiplier) - iValue ); - if( pField->multiplier != 1.0f ) - flTime /= pField->multiplier; + if( pField->multiplier <= 0.9999f || pField->multiplier >= 1.0001f ) + flTime = ( timebase * pField->multiplier - iValue ) / pField->multiplier; + else + flTime = timebase - iValue; } else { @@ -1559,7 +1590,7 @@ Writes current client data only for local client Other clients can grab the client state from entity_state_t ================== */ -void MSG_WriteClientData( sizebuf_t *msg, clientdata_t *from, clientdata_t *to, float timebase ) +void MSG_WriteClientData( sizebuf_t *msg, clientdata_t *from, clientdata_t *to, double timebase ) { delta_t *pField; delta_info_t *dt; @@ -1599,7 +1630,7 @@ MSG_ReadClientData Read the clientdata ================== */ -void MSG_ReadClientData( sizebuf_t *msg, clientdata_t *from, clientdata_t *to, float timebase ) +void MSG_ReadClientData( sizebuf_t *msg, clientdata_t *from, clientdata_t *to, double timebase ) { #if !XASH_DEDICATED delta_t *pField; @@ -1640,7 +1671,7 @@ Writes current client data only for local client Other clients can grab the client state from entity_state_t ================== */ -void MSG_WriteWeaponData( sizebuf_t *msg, weapon_data_t *from, weapon_data_t *to, float timebase, int index ) +void MSG_WriteWeaponData( sizebuf_t *msg, weapon_data_t *from, weapon_data_t *to, double timebase, int index ) { delta_t *pField; delta_info_t *dt; @@ -1679,7 +1710,7 @@ MSG_ReadWeaponData Read the clientdata ================== */ -void MSG_ReadWeaponData( sizebuf_t *msg, weapon_data_t *from, weapon_data_t *to, float timebase ) +void MSG_ReadWeaponData( sizebuf_t *msg, weapon_data_t *from, weapon_data_t *to, double timebase ) { delta_t *pField; delta_info_t *dt; @@ -1718,7 +1749,7 @@ If force is not set, then nothing at all will be generated if the entity is identical, under the assumption that the in-order delta code will catch it. ================== */ -void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, int delta_type, float timebase, int baseline ) +void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, int delta_type, double timebase, int baseline ) { delta_info_t *dt = NULL; delta_t *pField; @@ -1820,7 +1851,7 @@ If the delta removes the entity, entity_state_t->number will be set to MAX_EDICT Can go from either a baseline or a previous packet_entity ================== */ -qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state_t *to, int number, int delta_type, float timebase ) +qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state_t *to, int number, int delta_type, double timebase ) { #if !XASH_DEDICATED delta_info_t *dt = NULL; diff --git a/engine/common/net_encode.h b/engine/common/net_encode.h index 28484143..a00c9131 100644 --- a/engine/common/net_encode.h +++ b/engine/common/net_encode.h @@ -127,12 +127,12 @@ void MSG_WriteDeltaEvent( sizebuf_t *msg, struct event_args_s *from, struct even void MSG_ReadDeltaEvent( sizebuf_t *msg, struct event_args_s *from, struct event_args_s *to ); qboolean MSG_WriteDeltaMovevars( sizebuf_t *msg, struct movevars_s *from, struct movevars_s *to ); void MSG_ReadDeltaMovevars( sizebuf_t *msg, struct movevars_s *from, struct movevars_s *to ); -void MSG_WriteClientData( sizebuf_t *msg, struct clientdata_s *from, struct clientdata_s *to, float timebase ); -void MSG_ReadClientData( sizebuf_t *msg, struct clientdata_s *from, struct clientdata_s *to, float timebase ); -void MSG_WriteWeaponData( sizebuf_t *msg, struct weapon_data_s *from, struct weapon_data_s *to, float timebase, int index ); -void MSG_ReadWeaponData( sizebuf_t *msg, struct weapon_data_s *from, struct weapon_data_s *to, float timebase ); -void MSG_WriteDeltaEntity( struct entity_state_s *from, struct entity_state_s *to, sizebuf_t *msg, qboolean force, int type, float tbase, int ofs ); -qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, struct entity_state_s *from, struct entity_state_s *to, int num, int type, float timebase ); -int Delta_TestBaseline( struct entity_state_s *from, struct entity_state_s *to, qboolean player, float timebase ); +void MSG_WriteClientData( sizebuf_t *msg, struct clientdata_s *from, struct clientdata_s *to, double timebase ); +void MSG_ReadClientData( sizebuf_t *msg, struct clientdata_s *from, struct clientdata_s *to, double timebase ); +void MSG_WriteWeaponData( sizebuf_t *msg, struct weapon_data_s *from, struct weapon_data_s *to, double timebase, int index ); +void MSG_ReadWeaponData( sizebuf_t *msg, struct weapon_data_s *from, struct weapon_data_s *to, double timebase ); +void MSG_WriteDeltaEntity( struct entity_state_s *from, struct entity_state_s *to, sizebuf_t *msg, qboolean force, int type, double timebase, int ofs ); +qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, struct entity_state_s *from, struct entity_state_s *to, int num, int type, double timebase ); +int Delta_TestBaseline( struct entity_state_s *from, struct entity_state_s *to, qboolean player, double timebase ); #endif//NET_ENCODE_H