From 3cfdb1213b0c4d99a51314ead254655a55913e6a Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 11 Feb 2023 06:06:21 +0300 Subject: [PATCH] engine: client: consolidate modern and legacy protocol parsing functions, if possible --- engine/client/cl_parse.c | 289 ++++++++++----------------------------- engine/common/protocol.h | 3 + 2 files changed, 75 insertions(+), 217 deletions(-) diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index a2e4717f..0db7595b 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -843,15 +843,15 @@ void CL_ParseFileTransferFailed( sizebuf_t *msg ) CL_ParseServerData ================== */ -void CL_ParseServerData( sizebuf_t *msg ) +void CL_ParseServerData( sizebuf_t *msg, qboolean legacy ) { char gamefolder[MAX_QPATH]; qboolean background; int i; - Con_Reportf( "Serverdata packet received.\n" ); - cls.timestart = Sys_DoubleTime(); + Con_Reportf( "%s packet received.\n", legacy ? "Legacy serverdata" : "Serverdata" ); + cls.timestart = Sys_DoubleTime(); cls.demowaiting = false; // server is changed // wipe the client_t struct @@ -862,27 +862,46 @@ void CL_ParseServerData( sizebuf_t *msg ) // parse protocol version number i = MSG_ReadLong( msg ); - if( i != PROTOCOL_VERSION ) - Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION ); + if( legacy ) + { + if( i != PROTOCOL_LEGACY_VERSION ) + Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_LEGACY_VERSION ); + } + else + { + if( i != PROTOCOL_VERSION ) + Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION ); + } cl.servercount = MSG_ReadLong( msg ); cl.checksum = MSG_ReadLong( msg ); cl.playernum = MSG_ReadByte( msg ); cl.maxclients = MSG_ReadByte( msg ); clgame.maxEntities = MSG_ReadWord( msg ); - clgame.maxEntities = bound( MIN_EDICTS, clgame.maxEntities, MAX_EDICTS ); - clgame.maxModels = MSG_ReadWord( msg ); - Q_strncpy( clgame.mapname, MSG_ReadString( msg ), MAX_STRING ); - Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), MAX_STRING ); + if( legacy ) + { + clgame.maxEntities = bound( MIN_LEGACY_EDICTS, clgame.maxEntities, MAX_LEGACY_EDICTS ); + clgame.maxModels = 512; // ??? + } + else + { + clgame.maxEntities = bound( MIN_EDICTS, clgame.maxEntities, MAX_EDICTS ); + clgame.maxModels = MSG_ReadWord( msg ); + } + Q_strncpy( clgame.mapname, MSG_ReadString( msg ), sizeof( clgame.mapname )); + Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), sizeof( clgame.maptitle )); background = MSG_ReadOneBit( msg ); - Q_strncpy( gamefolder, MSG_ReadString( msg ), MAX_QPATH ); + Q_strncpy( gamefolder, MSG_ReadString( msg ), sizeof( gamefolder )); host.features = (uint)MSG_ReadLong( msg ); - // receive the player hulls - for( i = 0; i < MAX_MAP_HULLS * 3; i++ ) + if( !legacy ) { - host.player_mins[i/3][i%3] = MSG_ReadChar( msg ); - host.player_maxs[i/3][i%3] = MSG_ReadChar( msg ); + // receive the player hulls + for( i = 0; i < MAX_MAP_HULLS * 3; i++ ) + { + host.player_mins[i/3][i%3] = MSG_ReadChar( msg ); + host.player_maxs[i/3][i%3] = MSG_ReadChar( msg ); + } } if( clgame.maxModels > MAX_MODELS ) @@ -961,8 +980,11 @@ void CL_ParseServerData( sizebuf_t *msg ) COM_ClearCustomizationList( &cl.players[i].customdata, true ); CL_CreateCustomizationList(); - // request resources from server - CL_ServerCommand( true, "sendres %i\n", cl.servercount ); + if( !legacy ) + { + // request resources from server + CL_ServerCommand( true, "sendres %i\n", cl.servercount ); + } memset( &clgame.movevars, 0, sizeof( clgame.movevars )); memset( &clgame.oldmovevars, 0, sizeof( clgame.oldmovevars )); @@ -1137,7 +1159,7 @@ void CL_ParseClientData( sizebuf_t *msg ) CL_ParseBaseline ================== */ -void CL_ParseBaseline( sizebuf_t *msg ) +void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy ) { int i, newnum; entity_state_t nullstate; @@ -1150,8 +1172,15 @@ void CL_ParseBaseline( sizebuf_t *msg ) while( 1 ) { - newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS ); - if( newnum == LAST_EDICT ) break; // end of baselines + if( legacy ) + { + newnum = MSG_ReadWord( msg ); + } + else + { + newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS ); + if( newnum == LAST_EDICT ) break; // end of baselines + } player = CL_IsPlayerIndex( newnum ); if( newnum >= clgame.maxEntities ) @@ -1162,14 +1191,22 @@ void CL_ParseBaseline( sizebuf_t *msg ) ent->index = newnum; MSG_ReadDeltaEntity( msg, &ent->prevstate, &ent->baseline, newnum, player, 1.0f ); - } - cl.instanced_baseline_count = MSG_ReadUBitLong( msg, 6 ); + if( legacy ) + { + break; // only one baseline allowed in legacy protocol + } + } - for( i = 0; i < cl.instanced_baseline_count; i++ ) + if( !legacy ) { - newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS ); - MSG_ReadDeltaEntity( msg, &nullstate, &cl.instanced_baseline[i], newnum, false, 1.0f ); + cl.instanced_baseline_count = MSG_ReadUBitLong( msg, 6 ); + + for( i = 0; i < cl.instanced_baseline_count; i++ ) + { + newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS ); + MSG_ReadDeltaEntity( msg, &nullstate, &cl.instanced_baseline[i], newnum, false, 1.0f ); + } } } @@ -1317,7 +1354,7 @@ CL_UpdateUserinfo collect userinfo from all players ================ */ -void CL_UpdateUserinfo( sizebuf_t *msg ) +void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy ) { int slot, id; qboolean active; @@ -1328,7 +1365,8 @@ void CL_UpdateUserinfo( sizebuf_t *msg ) if( slot >= MAX_CLIENTS ) Host_Error( "CL_ParseServerMessage: svc_updateuserinfo >= MAX_CLIENTS\n" ); - id = MSG_ReadLong( msg ); // unique user ID + if( !legacy ) + id = MSG_ReadLong( msg ); // unique user ID player = &cl.players[slot]; active = MSG_ReadOneBit( msg ) ? true : false; @@ -1340,7 +1378,8 @@ void CL_UpdateUserinfo( sizebuf_t *msg ) player->topcolor = Q_atoi( Info_ValueForKey( player->userinfo, "topcolor" )); player->bottomcolor = Q_atoi( Info_ValueForKey( player->userinfo, "bottomcolor" )); player->spectator = Q_atoi( Info_ValueForKey( player->userinfo, "*hltv" )); - MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey )); + if( !legacy ) + MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey )); if( slot == cl.playernum ) memcpy( &gameui.playerinfo, player, sizeof( player_info_t )); } @@ -2230,13 +2269,13 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ) break; case svc_serverdata: Cbuf_Execute(); // make sure any stuffed commands are done - CL_ParseServerData( msg ); + CL_ParseServerData( msg, false ); break; case svc_lightstyle: CL_ParseLightStyle( msg ); break; case svc_updateuserinfo: - CL_UpdateUserinfo( msg ); + CL_UpdateUserinfo( msg, false ); break; case svc_deltatable: Delta_ParseTableField( msg ); @@ -2266,7 +2305,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ) cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart; break; case svc_spawnbaseline: - CL_ParseBaseline( msg ); + CL_ParseBaseline( msg, false ); break; case svc_temp_entity: CL_ParseTempEntity( msg ); @@ -2403,156 +2442,6 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ) } } -/* -================== -CL_ParseBaseline -================== -*/ -void CL_LegacyParseBaseline( sizebuf_t *msg ) -{ - int i, newnum; - qboolean player; - cl_entity_t *ent; - - Delta_InitClient (); // finalize client delta's - - newnum = MSG_ReadWord( msg ); - player = CL_IsPlayerIndex( newnum ); - - if( newnum >= clgame.maxEntities ) - Host_Error( "CL_AllocEdict: no free edicts\n" ); - - ent = CL_EDICT_NUM( newnum ); - memset( &ent->prevstate, 0, sizeof( ent->prevstate )); - ent->index = newnum; - - MSG_ReadDeltaEntity( msg, &ent->prevstate, &ent->baseline, newnum, player, 1.0f ); - -} - -/* -================== -CL_ParseServerData -================== -*/ -void CL_ParseLegacyServerData( sizebuf_t *msg ) -{ - string gamefolder; - qboolean background; - int i; - - Con_Reportf( "Legacy serverdata packet received.\n" ); - - cls.timestart = Sys_DoubleTime(); - - cls.demowaiting = false; // server is changed - //clgame.load_sequence++; // now all hud sprites are invalid - - // wipe the client_t struct - if( !cls.changelevel && !cls.changedemo ) - CL_ClearState (); - cls.state = ca_connected; - - // parse protocol version number - i = MSG_ReadLong( msg ); - //cls.serverProtocol = i; - - if( i != PROTOCOL_LEGACY_VERSION ) - Host_Error( "Server uses invalid protocol (%i should be %i)\n", i, PROTOCOL_LEGACY_VERSION ); - - cl.servercount = MSG_ReadLong( msg ); - cl.checksum = MSG_ReadLong( msg ); - cl.playernum = MSG_ReadByte( msg ); - cl.maxclients = MSG_ReadByte( msg ); - clgame.maxEntities = MSG_ReadWord( msg ); - clgame.maxEntities = bound( 30, clgame.maxEntities, 4096 ); - clgame.maxModels = 512; - Q_strncpy( clgame.mapname, MSG_ReadString( msg ), MAX_STRING ); - Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), MAX_STRING ); - background = MSG_ReadOneBit( msg ); - Q_strncpy( gamefolder, MSG_ReadString( msg ), MAX_STRING ); - host.features = (uint)MSG_ReadLong( msg ); - - // Re-init hud video, especially if we changed game directories - clgame.dllFuncs.pfnVidInit(); - - if( Con_FixedFont( )) - { - // seperate the printfs so the server message can have a color - Con_Print( "\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n" ); - Con_Print( va( "%c%s\n\n", 2, clgame.maptitle )); - } - - // multiplayer game? - if( cl.maxclients > 1 ) - { - // allow console in multiplayer games - host.allow_console = true; - - // loading user settings - CSCR_LoadDefaultCVars( "user.scr" ); - - if( r_decals->value > mp_decals.value ) - Cvar_SetValue( "r_decals", mp_decals.value ); - } - else Cvar_Reset( "r_decals" ); - - // set the background state - if( cls.demoplayback && ( cls.demonum != -1 )) - cl.background = true; - else cl.background = background; - - if( cl.background ) // tell the game parts about background state - Cvar_FullSet( "cl_background", "1", FCVAR_READ_ONLY ); - else Cvar_FullSet( "cl_background", "0", FCVAR_READ_ONLY ); - - if( !cls.changelevel ) - { - // continue playing if we are changing level - S_StopBackgroundTrack (); - } - - if( !cls.changedemo ) - UI_SetActiveMenu( cl.background ); - else if( !cls.demoplayback ) - Key_SetKeyDest( key_menu ); - - // don't reset cursor in background mode - if( cl.background ) - IN_MouseRestorePos(); - - // will be changed later - cl.viewentity = cl.playernum + 1; - gameui.globals->maxClients = cl.maxclients; - Q_strncpy( gameui.globals->maptitle, clgame.maptitle, sizeof( gameui.globals->maptitle )); - - if( !cls.changelevel && !cls.changedemo ) - CL_InitEdicts (); // re-arrange edicts - - // get splash name - if( cls.demoplayback && ( cls.demonum != -1 )) - Cvar_Set( "cl_levelshot_name", va( "levelshots/%s_%s", cls.demoname, refState.wideScreen ? "16x9" : "4x3" )); - else Cvar_Set( "cl_levelshot_name", va( "levelshots/%s_%s", clgame.mapname, refState.wideScreen ? "16x9" : "4x3" )); - Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar - - if(( cl_allow_levelshots->value && !cls.changelevel ) || cl.background ) - { - if( !FS_FileExists( va( "%s.bmp", cl_levelshot_name->string ), true )) - Cvar_Set( "cl_levelshot_name", "*black" ); // render a black screen - cls.scrshot_request = scrshot_plaque; // request levelshot even if exist (check filetime) - } - - for( i = 0; i < MAX_CLIENTS; i++ ) - COM_ClearCustomizationList( &cl.players[i].customdata, true ); - CL_CreateCustomizationList(); - - memset( &clgame.movevars, 0, sizeof( clgame.movevars )); - memset( &clgame.oldmovevars, 0, sizeof( clgame.oldmovevars )); - memset( &clgame.centerPrint, 0, sizeof( clgame.centerPrint )); - cl.video_prepped = false; - cl.audio_prepped = false; -} - /* ================== CL_ParseStaticEntity @@ -2628,8 +2517,6 @@ void CL_LegacyParseStaticEntity( sizebuf_t *msg ) R_AddEfrags( ent ); // add link } - - void CL_LegacyParseSoundPacket( sizebuf_t *msg, qboolean is_ambient ) { vec3_t pos; @@ -2761,36 +2648,6 @@ void CL_LegacyPrecacheEvent( sizebuf_t *msg ) CL_SetEventIndex( cl.event_precache[eventIndex], eventIndex ); } - -void CL_LegacyUpdateUserinfo( sizebuf_t *msg ) -{ - int slot, id = 0; - qboolean active; - player_info_t *player; - - slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS ); - - if( slot >= MAX_CLIENTS ) - Host_Error( "CL_ParseServerMessage: svc_updateuserinfo >= MAX_CLIENTS\n" ); - - //id = MSG_ReadLong( msg ); // unique user ID - player = &cl.players[slot]; - active = MSG_ReadOneBit( msg ) ? true : false; - - if( active ) - { - Q_strncpy( player->userinfo, MSG_ReadString( msg ), sizeof( player->userinfo )); - Q_strncpy( player->name, Info_ValueForKey( player->userinfo, "name" ), sizeof( player->name )); - Q_strncpy( player->model, Info_ValueForKey( player->userinfo, "model" ), sizeof( player->model )); - player->topcolor = Q_atoi( Info_ValueForKey( player->userinfo, "topcolor" )); - player->bottomcolor = Q_atoi( Info_ValueForKey( player->userinfo, "bottomcolor" )); - player->spectator = Q_atoi( Info_ValueForKey( player->userinfo, "*hltv" )); - //MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey )); - - if( slot == cl.playernum ) memcpy( &gameui.playerinfo, player, sizeof( player_info_t )); - } - else memset( player, 0, sizeof( *player )); -} #if XASH_LOW_MEMORY == 0 #define MAX_LEGACY_RESOURCES 2048 #elif XASH_LOW_MEMORY == 2 @@ -2994,13 +2851,13 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message ) break; case svc_serverdata: Cbuf_Execute(); // make sure any stuffed commands are done - CL_ParseLegacyServerData( msg ); + CL_ParseServerData( msg, true ); break; case svc_lightstyle: CL_ParseLightStyle( msg ); break; case svc_updateuserinfo: - CL_LegacyUpdateUserinfo( msg ); + CL_UpdateUserinfo( msg, true ); break; case svc_deltatable: Delta_ParseTableField( msg ); @@ -3030,7 +2887,7 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message ) cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart; break; case svc_spawnbaseline: - CL_LegacyParseBaseline( msg ); + CL_ParseBaseline( msg, true ); break; case svc_temp_entity: CL_ParseTempEntity( msg ); @@ -3050,7 +2907,6 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message ) break; case svc_legacy_modelindex: CL_LegacyPrecacheModel( msg ); - break; case svc_legacy_soundindex: CL_LegacyPrecacheSound( msg ); @@ -3066,7 +2922,6 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message ) CL_ParseRestore( msg ); break; case svc_legacy_eventindex: - //CL_ParseFinaleCutscene( msg, 3 ); CL_LegacyPrecacheEvent(msg); break; case svc_weaponanim: diff --git a/engine/common/protocol.h b/engine/common/protocol.h index aba1fd5e..7d525677 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -302,6 +302,9 @@ extern const char *clc_strings[clc_lastmsg+1]; #define MAX_LEGACY_TOTAL_CMDS 16 // 28 - 16 = 12 real legacy max backup #define MAX_LEGACY_BACKUP_CMDS 12 +#define MAX_LEGACY_EDICTS (1 << MAX_LEGACY_ENTITY_BITS) // 4096 edicts +#define MIN_LEGACY_EDICTS 30 + // Master Server protocol #define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0" // TODO: implement IP filter