From 6aa29e22d25187674e7de1a0ca051e98581d3fa4 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Tue, 16 Apr 2024 03:40:34 +0300 Subject: [PATCH] implement delta tests --- engine/common/net_encode.c | 148 ++++++++++++++++++++++++++++++++++++- engine/common/tests.h | 4 +- public/xash3d_mathlib.h | 3 +- 3 files changed, 150 insertions(+), 5 deletions(-) diff --git a/engine/common/net_encode.c b/engine/common/net_encode.c index 7291d325..20ec353b 100644 --- a/engine/common/net_encode.c +++ b/engine/common/net_encode.c @@ -335,6 +335,43 @@ static const delta_field_t ent_fields[] = { NULL }, }; +#if XASH_ENGINE_TESTS +typedef struct delta_test_struct_t +{ + char dt_string[128]; // always signed + float dt_timewindow_big; // always signed + float dt_timewindow_8; // always signed + float dt_angle; // always_signed + float dt_float_signed; + float dt_float_unsigned; + int32_t dt_integer_signed; + uint32_t dt_integer_unsigned; + int16_t dt_short_signed; + uint16_t dt_short_unsigned; + int8_t dt_byte_signed; + uint8_t dt_byte_unsigned; +} delta_test_struct_t; + +#define TEST_DEF( x ) #x, offsetof( delta_test_struct_t, x ), sizeof( ((delta_test_struct_t *)0)->x ) + +static const delta_field_t test_fields[] = +{ +{ TEST_DEF( dt_string ) }, +{ TEST_DEF( dt_timewindow_big )}, +{ TEST_DEF( dt_timewindow_8 )}, +{ TEST_DEF( dt_angle ) }, +{ TEST_DEF( dt_float_signed ) }, +{ TEST_DEF( dt_float_unsigned ) }, +{ TEST_DEF( dt_integer_signed ) }, +{ TEST_DEF( dt_integer_unsigned ) }, +{ TEST_DEF( dt_short_signed ) }, +{ TEST_DEF( dt_short_unsigned ) }, +{ TEST_DEF( dt_byte_signed ) }, +{ TEST_DEF( dt_byte_unsigned ) }, +{ NULL }, +}; +#endif + enum { DT_EVENT_T = 0, @@ -345,6 +382,10 @@ enum DT_ENTITY_STATE_T, DT_ENTITY_STATE_PLAYER_T, DT_CUSTOM_ENTITY_STATE_T, +#if XASH_ENGINE_TESTS + DT_DELTA_TEST_STRUCT_T, +#endif + DT_STRUCT_COUNT }; static delta_info_t dt_info[] = @@ -357,7 +398,10 @@ static delta_info_t dt_info[] = [DT_ENTITY_STATE_T] = { "entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) }, [DT_ENTITY_STATE_PLAYER_T] = { "entity_state_player_t", ent_fields, NUM_FIELDS( ent_fields ) }, [DT_CUSTOM_ENTITY_STATE_T] = { "custom_entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) }, -{ NULL }, +#if XASH_ENGINE_TESTS +[DT_DELTA_TEST_STRUCT_T] = { "delta_test_struct_t", test_fields, NUM_FIELDS( test_fields ) }, +#endif +[DT_STRUCT_COUNT] = { NULL }, }; static delta_info_t *Delta_FindStruct( const char *name ) @@ -431,9 +475,7 @@ static void Delta_CustomEncode( delta_info_t *dt, const void *from, const void * dt->pFields[i].bInactive = false; if( dt->userCallback ) - { dt->userCallback( dt->pFields, from, to ); - } } static delta_field_t *Delta_FindFieldInfo( const delta_field_t *pInfo, const char *fieldName ) @@ -2136,3 +2178,103 @@ void GAME_EXPORT Delta_UnsetFieldByIndex( delta_t *pFields, int fieldNumber ) dt->pFields[fieldNumber].bInactive = true; } + +#if XASH_ENGINE_TESTS +#include "tests.h" + +void Test_RunDelta( void ) +{ + delta_info_t *dt = &dt_info[DT_DELTA_TEST_STRUCT_T]; + delta_test_struct_t from, to = { 0 }; + delta_test_struct_t null = { 0 }; + sizebuf_t msg; + int i; + char buffer[4096] = { 0 }; + const double timebase = 123.123; + + // a1ba: netbuffer bitmasks are initialized in netchan for some reason + // initialize it ourselves just in case + MSG_InitMasks(); // initialize bit-masks + + Delta_AddField( dt, "dt_string", DT_STRING, false, 1, 1.0f, 1.0f ); + Delta_AddField( dt, "dt_timewindow_big", DT_TIMEWINDOW_BIG, false, 24, 1000.f, 1.0f ); + Delta_AddField( dt, "dt_timewindow_8", DT_TIMEWINDOW_8, false, 8, 1.0f, 1.0f ); + Delta_AddField( dt, "dt_angle", DT_ANGLE, false, 16, 1.0f, 1.0f ); + Delta_AddField( dt, "dt_float_signed", DT_FLOAT, true, 22, 100.0f, 1.0f ); + Delta_AddField( dt, "dt_float_unsigned", DT_FLOAT, false, 24, 10000.0f, 0.1f ); + Delta_AddField( dt, "dt_integer_signed", DT_INTEGER, true, 24, 1.0f, 1.0f ); + Delta_AddField( dt, "dt_integer_unsigned", DT_INTEGER, false, 24, 1.0f, 1.0f ); + Delta_AddField( dt, "dt_short_signed", DT_SHORT, true, 24, 2.0f, 1.0f ); + Delta_AddField( dt, "dt_short_unsigned", DT_SHORT, false, 15, 1.0f, 1.0f ); + Delta_AddField( dt, "dt_byte_signed", DT_BYTE, true, 6, 1.0f, 1.0f ); + Delta_AddField( dt, "dt_byte_unsigned", DT_BYTE, false, 8, 1.0f, 1.0f ); + + Q_strncpy( from.dt_string, "test data check it's the same", sizeof( from.dt_string )); + from.dt_timewindow_big = timebase + 2.3456; + from.dt_timewindow_8 = timebase + 0.0234; + from.dt_angle = 160.245f; + from.dt_float_signed = -15.123f; + from.dt_float_unsigned = 1235.321f; + from.dt_integer_signed = -412784; + from.dt_integer_unsigned = 123453; + from.dt_short_signed = -12312; + from.dt_short_unsigned = 32131; + from.dt_byte_signed = 16; + from.dt_byte_unsigned = 218; + + MSG_Init( &msg, "test message", buffer, sizeof( buffer )); + + for( i = 0; i < dt->numFields; i++ ) + Delta_WriteField( &msg, &dt->pFields[i], &null, &from, timebase ); + + MSG_SeekToBit( &msg, 0, SEEK_SET ); + + for( i = 0; i < dt->numFields; i++ ) + Delta_ReadField( &msg, &dt->pFields[i], &null, &to, timebase ); + + Con_Printf( "struct as encoded to delta:\n" ); + TASSERT_STR( from.dt_string, to.dt_string ); + + // the epsilon value is derived from multiplier value + TASSERT( Q_equal_e( from.dt_timewindow_big, to.dt_timewindow_big, 0.001f )); + + // dt_timewindow_8 type has multiplier locked at 100.0f + TASSERT( Q_equal_e( from.dt_timewindow_8, to.dt_timewindow_8, 0.01f )); + TASSERT( Q_equal_e( from.dt_angle, to.dt_angle, 0.1f )); + TASSERT( Q_equal_e( from.dt_float_signed, to.dt_float_signed, 0.01f )); + + // dt_float_unsigned has post-multiplier that doesn't affect network data + // and therefore should be reverted back when comparing + TASSERT( Q_equal_e( from.dt_float_unsigned, to.dt_float_unsigned * 10.f , 0.01f )); + + TASSERT_EQi( from.dt_integer_signed, to.dt_integer_signed ); + TASSERT_EQi( from.dt_integer_unsigned, to.dt_integer_unsigned ); + TASSERT_EQi( from.dt_short_signed, to.dt_short_signed ); + TASSERT_EQi( from.dt_short_unsigned, to.dt_short_unsigned ); + TASSERT_EQi( from.dt_byte_signed, to.dt_byte_signed ); + TASSERT_EQi( from.dt_byte_unsigned, to.dt_byte_unsigned ); + + Con_Printf( "from.dt_timewindow_big = %f\n", from.dt_timewindow_big ); + Con_Printf( "to.dt_timewindow_big = %f\n", to.dt_timewindow_big ); + Con_Printf( "from.dt_timewindow_8 = %f\n", from.dt_timewindow_8 ); + Con_Printf( "to.dt_timewindow_8 = %f\n", to.dt_timewindow_8 ); + Con_Printf( "from.dt_angle = %f\n", from.dt_angle ); + Con_Printf( "to.dt_angle = %f\n", to.dt_angle ); + Con_Printf( "from.dt_float_signed = %f\n", from.dt_float_signed ); + Con_Printf( "to.dt_float_signed = %f\n", to.dt_float_signed ); + Con_Printf( "from.dt_float_unsigned = %f\n", from.dt_float_unsigned ); + Con_Printf( "to.dt_float_unsigned = %f\n", to.dt_float_unsigned ); + Con_Printf( "from.dt_integer_signed = %i\n", from.dt_integer_signed ); + Con_Printf( "to.dt_integer_signed = %i\n", to.dt_integer_signed ); + Con_Printf( "from.dt_integer_unsigned = %i\n", from.dt_integer_unsigned ); + Con_Printf( "to.dt_integer_unsigned = %i\n", to.dt_integer_unsigned ); + Con_Printf( "from.dt_short_signed = %i\n", from.dt_short_signed ); + Con_Printf( "to.dt_short_signed = %i\n", to.dt_short_signed ); + Con_Printf( "from.dt_short_unsigned = %i\n", from.dt_short_unsigned ); + Con_Printf( "to.dt_short_unsigned = %i\n", to.dt_short_unsigned ); + Con_Printf( "from.dt_byte_signed = %i\n", from.dt_byte_signed ); + Con_Printf( "to.dt_byte_signed = %i\n", to.dt_byte_signed ); + Con_Printf( "from.dt_byte_unsigned = %i\n", from.dt_byte_unsigned ); + Con_Printf( "to.dt_byte_unsigned = %i\n", to.dt_byte_unsigned ); +} +#endif // XASH_ENGINE_TESTS diff --git a/engine/common/tests.h b/engine/common/tests.h index 48c06551..eeedcd06 100644 --- a/engine/common/tests.h +++ b/engine/common/tests.h @@ -39,13 +39,15 @@ void Test_RunCon( void ); void Test_RunVOX( void ); void Test_RunIPFilter( void ); void Test_RunGamma( void ); +void Test_RunDelta( void ); #define TEST_LIST_0 \ Test_RunLibCommon(); \ Test_RunCommon(); \ Test_RunCmd(); \ Test_RunCvar(); \ - Test_RunIPFilter(); + Test_RunIPFilter(); \ + Test_RunDelta(); #define TEST_LIST_0_CLIENT \ Test_RunCon(); \ diff --git a/public/xash3d_mathlib.h b/public/xash3d_mathlib.h index 55b759fc..4f87a0aa 100644 --- a/public/xash3d_mathlib.h +++ b/public/xash3d_mathlib.h @@ -76,7 +76,8 @@ GNU General Public License for more details. #define Q_min( a, b ) (((a) < (b)) ? (a) : (b)) #define Q_max( a, b ) (((a) > (b)) ? (a) : (b)) -#define Q_equal( a, b ) (((a) > ((b) - EQUAL_EPSILON)) && ((a) < ((b) + EQUAL_EPSILON))) +#define Q_equal_e( a, b, e ) (((a) > ((b) - (e))) && ((a) < ((b) + (e)))) +#define Q_equal( a, b ) Q_equal_e( a, b, EQUAL_EPSILON ) #define Q_recip( a ) ((float)(1.0f / (float)(a))) #define Q_floor( a ) ((float)(int)(a)) #define Q_ceil( a ) ((float)(int)((a) + 1))