diff --git a/engine/client/cl_custom.c b/engine/client/cl_custom.c index d2f62c4b..5c009f99 100644 --- a/engine/client/cl_custom.c +++ b/engine/client/cl_custom.c @@ -32,11 +32,14 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource ) } // resource was missed on server -// if( pResource->nDownloadSize <= 0 ) -// return true; + if( pResource->nDownloadSize == -1 ) + { + ClearBits( pResource->ucFlags, RES_FATALIFMISSING ); + return true; + } if( pResource->type == t_sound ) - Q_strncpy( filepath, va( "sound/%s", pResource->szFileName ), sizeof( filepath )); + Q_strncpy( filepath, va( "%s%s", DEFAULT_SOUNDPATH, pResource->szFileName ), sizeof( filepath )); else Q_strncpy( filepath, pResource->szFileName, sizeof( filepath )); if( !COM_IsSafeFileToDownload( filepath )) @@ -67,7 +70,8 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource ) } MSG_BeginClientCmd( msg, clc_stringcmd ); - MSG_WriteString( msg, va( "dlfile %s", pResource->szFileName )); + MSG_WriteString( msg, va( "dlfile %s", filepath )); + host.downloadcount++; return false; } diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index 57d2244b..d7607240 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -2246,25 +2246,29 @@ CL_FindModelIndex */ int CL_FindModelIndex( const char *m ) { + char filepath[MAX_QPATH]; static float lasttimewarn; int i; if( !COM_CheckString( m )) return 0; + Q_strncpy( filepath, m, sizeof( filepath )); + COM_FixSlashes( filepath ); + for( i = 0; i < cl.nummodels; i++ ) { if( !cl.models[i+1] ) continue; - if( !Q_stricmp( cl.models[i+1]->name, m )) - return i; + if( !Q_stricmp( cl.models[i+1]->name, filepath )) + return i+1; } if( lasttimewarn < host.realtime ) { // tell user about problem (but don't spam console) - Con_Printf( S_ERROR "%s not precached\n", m ); + Con_Printf( S_ERROR "%s not precached\n", filepath ); lasttimewarn = host.realtime + 1.0f; } diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index a3a6e54f..ec119f58 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -88,9 +88,13 @@ qboolean CL_Initialized( void ) //====================================================================== qboolean CL_IsInGame( void ) { - if( host.type == HOST_DEDICATED ) return true; // always active for dedicated servers - if( CL_GetMaxClients() > 1 ) return true; // always active for multiplayer - return ( cls.key_dest == key_game ); // active if not menu or console + if( host.type == HOST_DEDICATED ) + return true; // always active for dedicated servers + + if( cl.background || CL_GetMaxClients() > 1 ) + return true; // always active for multiplayer or background map + + return ( cls.key_dest == key_game ); // active if not menu or console } qboolean CL_IsInMenu( void ) @@ -623,7 +627,7 @@ void CL_CreateCmd( void ) { VectorCopy( angles, pcmd->cmd.viewangles ); VectorCopy( angles, cl.viewangles ); - pcmd->cmd.msec = 0; + if( !cl.background ) pcmd->cmd.msec = 0; } // demo always have commands so don't overwrite them @@ -1671,103 +1675,6 @@ void CL_SetupOverviewParams( void ) } } -/* -====================== -CL_PrepSound - -Call before entering a new level, or after changing dlls -====================== -*/ -void CL_PrepSound( void ) -{ - int i, sndcount; - - MsgDev( D_NOTE, "CL_PrepSound: %s\n", clgame.mapname ); - for( i = 0, sndcount = 0; i < MAX_SOUNDS && cl.sound_precache[i+1][0]; i++ ) - sndcount++; // total num sounds - - S_BeginRegistration(); - - for( i = 0; i < MAX_SOUNDS && cl.sound_precache[i+1][0]; i++ ) - { - cl.sound_index[i+1] = S_RegisterSound( cl.sound_precache[i+1] ); - Cvar_SetValue( "scr_loading", scr_loading->value + 5.0f / sndcount ); - if( cl_allow_levelshots->value || host_developer.value || cl.background ) - SCR_UpdateScreen(); - } - - S_EndRegistration(); - cl.audio_prepped = true; -} - -/* -================= -CL_PrepVideo - -Call before entering a new level, or after changing dlls -================= -*/ -void CL_PrepVideo( void ) -{ - model_t *mod; - int i; - - if( !cl.models[WORLD_INDEX] ) - return; // no map loaded - - Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar - MsgDev( D_NOTE, "CL_PrepVideo: %s\n", clgame.mapname ); - - // let the render dll load the map - world.loading = true; - cl.worldmodel = Mod_LoadModel( cl.models[WORLD_INDEX], true ); - world.loading = false; - Cvar_SetValue( "scr_loading", 25.0f ); - - SCR_UpdateScreen(); - - for( i = WORLD_INDEX; i < cl.nummodels - 1; i++ ) - { - Mod_LoadModel( cl.models[i+1], false ); - Cvar_SetValue( "scr_loading", scr_loading->value + 75.0f / cl.nummodels ); - if( cl_allow_levelshots->value || host_developer.value || cl.background ) - SCR_UpdateScreen(); - } - - // load tempent sprites (glowshell, muzzleflashes etc) - CL_LoadClientSprites (); - - // invalidate all decal indexes - memset( cl.decal_index, 0, sizeof( cl.decal_index )); - - CL_ClearWorld (); - - R_NewMap(); // tell the render about new map - - CL_SetupOverviewParams(); // set overview bounds - - if( clgame.drawFuncs.R_NewMap != NULL ) - clgame.drawFuncs.R_NewMap(); - - // release unused SpriteTextures - for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ ) - { - if( mod->needload == NL_UNREFERENCED && COM_CheckString( mod->name )) - Mod_UnloadSpriteModel( mod ); - } - - Mod_FreeUnused (); - - Cvar_SetValue( "scr_loading", 100.0f ); // all done - - if( !host_developer.value ) - Con_ClearNotify(); // clear any lines of console text - - cl.video_prepped = true; - - SCR_UpdateScreen (); -} - /* ================= CL_ConnectionlessPacket @@ -1803,7 +1710,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) } CL_Reconnect( true ); - UI_SetActiveMenu( false ); + UI_SetActiveMenu( cl.background ); } else if( !Q_strcmp( c, "info" )) { @@ -2136,7 +2043,7 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename ) if( COM_CheckString( filename ) && successfully_received ) { if( filename[0] != '!' ) - Con_Printf( "Processing %s\n", filename ); + Con_Printf( "processing %s\n", filename ); } else if( !successfully_received ) { @@ -2152,15 +2059,23 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename ) { if( !Q_strnicmp( filename, "!MD5", 4 )) { - COM_HexConvert( pfilename + 4, 32, rgucMD5_hash ); + COM_HexConvert( filename + 4, 32, rgucMD5_hash ); if( !memcmp( p->rgucMD5_hash, rgucMD5_hash, 16 )) break; } else { - if( !Q_stricmp( p->szFileName, filename )) - break; + if( p->type == t_generic ) + { + if( !Q_stricmp( p->szFileName, filename )) + break; + } + else + { + if( !Q_stricmp( p->szFileName, pfilename )) + break; + } } } @@ -2200,6 +2115,11 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename ) if( cls.state != ca_disconnected ) { + host.downloadcount = 0; + + for( p = cl.resourcesneeded.pNext; p != &cl.resourcesneeded; p = p->pNext ) + host.downloadcount++; + if( cl.resourcesneeded.pNext == &cl.resourcesneeded ) { byte msg_buf[MAX_INIT_MSG]; @@ -2312,33 +2232,10 @@ void CL_Physinfo_f( void ) Con_Printf( "Total %i symbols\n", Q_strlen( cls.physinfo )); } -/* -================= -CL_Precache_f - -The server will send this command right -before allowing the client into the server -================= -*/ -void CL_Precache_f( void ) -{ - int spawncount; - - spawncount = Q_atoi( Cmd_Argv( 1 )); - - CL_PrepSound(); - CL_PrepVideo(); - - MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd ); - MSG_WriteString( &cls.netchan.message, va( "spawn %i\n", spawncount )); -} - qboolean CL_PrecacheResources( void ) { resource_t *pRes; - S_BeginRegistration(); - // NOTE: world need to be loaded as first model for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext ) { @@ -2366,7 +2263,6 @@ qboolean CL_PrecacheResources( void ) if( FBitSet( pRes->ucFlags, RES_FATALIFMISSING )) { - S_EndRegistration(); CL_Disconnect_f(); return false; } @@ -2374,6 +2270,8 @@ qboolean CL_PrecacheResources( void ) } } + S_BeginRegistration(); + // precache all the remaining resources where order is doesn't matter for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext ) { @@ -2383,25 +2281,33 @@ qboolean CL_PrecacheResources( void ) switch( pRes->type ) { case t_sound: - if( FBitSet( pRes->ucFlags, RES_WASMISSING )) + if( pRes->nIndex != -1 ) { - cl.sound_precache[pRes->nIndex][0] = 0; - cl.sound_index[pRes->nIndex] = 0; + if( FBitSet( pRes->ucFlags, RES_WASMISSING )) + { + cl.sound_precache[pRes->nIndex][0] = 0; + cl.sound_index[pRes->nIndex] = 0; + } + else + { + Q_strncpy( cl.sound_precache[pRes->nIndex], pRes->szFileName, sizeof( cl.sound_precache[0] )); + cl.sound_index[pRes->nIndex] = S_RegisterSound( pRes->szFileName ); + + if( !cl.sound_index[pRes->nIndex] ) + { + if( FBitSet( pRes->ucFlags, RES_FATALIFMISSING )) + { + S_EndRegistration(); + CL_Disconnect_f(); + return false; + } + } + } } else { - Q_strncpy( cl.sound_precache[pRes->nIndex], pRes->szFileName, sizeof( cl.sound_precache[0] )); - cl.sound_index[pRes->nIndex] = S_RegisterSound( pRes->szFileName ); - - if( !cl.sound_index[pRes->nIndex] ) - { - if( FBitSet( pRes->ucFlags, RES_FATALIFMISSING )) - { - S_EndRegistration(); - CL_Disconnect_f(); - return false; - } - } + // client sounds + S_RegisterSound( pRes->szFileName ); } break; case t_skin: @@ -2410,20 +2316,27 @@ qboolean CL_PrecacheResources( void ) cl.nummodels = Q_max( cl.nummodels, pRes->nIndex + 1 ); if( pRes->szFileName[0] != '*' ) { - cl.models[pRes->nIndex] = Mod_ForName( pRes->szFileName, false, true ); - - if( cl.models[pRes->nIndex] == NULL ) + if( pRes->nIndex != -1 ) { - if( pRes->ucFlags != 0 ) - MsgDev( D_WARN, "model %s not found and not available\n", pRes->szFileName ); + cl.models[pRes->nIndex] = Mod_ForName( pRes->szFileName, false, true ); - if( FBitSet( pRes->ucFlags, RES_FATALIFMISSING )) + if( cl.models[pRes->nIndex] == NULL ) { - S_EndRegistration(); - CL_Disconnect_f(); - return false; + if( pRes->ucFlags != 0 ) + MsgDev( D_WARN, "model %s not found and not available\n", pRes->szFileName ); + + if( FBitSet( pRes->ucFlags, RES_FATALIFMISSING )) + { + S_EndRegistration(); + CL_Disconnect_f(); + return false; + } } } + else + { + CL_LoadClientSprite( pRes->szFileName ); + } } break; case t_decal: @@ -2611,7 +2524,6 @@ void CL_InitLocal( void ) Cmd_AddCommand ("reconnect", CL_Reconnect_f, "reconnect to current level" ); Cmd_AddCommand ("rcon", CL_Rcon_f, "sends a command to the server console (rcon_password and rcon_address required)" ); - Cmd_AddCommand ("precache", CL_Precache_f, "precache specified resource (by index)" ); } //============================================================================ @@ -2662,9 +2574,6 @@ void Host_ClientBegin( void ) // if client is not active, do nothing if( !cls.initialized ) return; - // evaluate console animation - Con_RunConsole (); - // exec console commands Cbuf_Execute (); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 1603dcb9..e5d26119 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -654,6 +654,7 @@ qboolean CL_RequestMissingResources( void ) if( p == &cl.resourcesneeded ) { cls.dl.doneregistering = true; + host.downloadcount = 0; cls.dl.custom = false; } else if( !FBitSet( p->ucFlags, RES_WASMISSING )) @@ -673,6 +674,9 @@ void CL_BatchResourceRequest( void ) MSG_Init( &msg, "Resource Batch", data, sizeof( data )); + // client resources is not precached by server + CL_AddClientResources(); + for( p = cl.resourcesneeded.pNext; p && p != &cl.resourcesneeded; p = n ) { n = p->pNext; @@ -748,6 +752,7 @@ void CL_BatchResourceRequest( void ) CL_RegisterResources( &msg ); } + Msg( "download request %d bytes\n", MSG_GetNumBytesWritten( &msg )); Netchan_CreateFragments( &cls.netchan, &msg ); Netchan_FragSend( &cls.netchan ); } @@ -765,7 +770,7 @@ int CL_EstimateNeededResources( void ) { case t_sound: nSize = FS_FileSize( va( "sound/%s", p->szFileName ), false ); - if( p->szFileName[0] != '*' && ( nSize == 0 || nSize == -1 )) + if( p->szFileName[0] != '*' && nSize == -1 ) { SetBits( p->ucFlags, RES_WASMISSING ); nTotalSize += p->nDownloadSize; @@ -773,7 +778,7 @@ int CL_EstimateNeededResources( void ) break; case t_model: nSize = FS_FileSize( p->szFileName, false ); - if( p->szFileName[0] != '*' && p->ucFlags != 0 && ( nSize == 0 || nSize == -1 )) + if( p->szFileName[0] != '*' && p->ucFlags && nSize == -1 ) { SetBits( p->ucFlags, RES_WASMISSING ); nTotalSize += p->nDownloadSize; @@ -783,7 +788,7 @@ int CL_EstimateNeededResources( void ) case t_generic: case t_eventscript: nSize = FS_FileSize( p->szFileName, false ); - if( nSize == 0 || nSize == -1 ) + if( nSize == -1 ) { SetBits( p->ucFlags, RES_WASMISSING ); nTotalSize += p->nDownloadSize; @@ -1152,20 +1157,14 @@ void CL_ParseServerData( sizebuf_t *msg ) cls.scrshot_request = scrshot_plaque; // request levelshot even if exist (check filetime) } - // begin fetching modellist - MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd ); -#if 0 - MSG_WriteString( &cls.netchan.message, va( "modellist %i\n", cl.servercount )); -#else - MSG_WriteString( &cls.netchan.message, va( "sendres %i\n", cl.servercount )); -#endif - // need to prep refresh at next oportunity - cl.video_prepped = false; - cl.audio_prepped = false; + // 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 )); memset( &clgame.centerPrint, 0, sizeof( clgame.centerPrint )); + cl.video_prepped = false; + cl.audio_prepped = false; } /* @@ -2277,6 +2276,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ) { size_t bufStart, playerbytes; int cmd, param1, param2; + int old_background; cls_message_debug.parsing = true; // begin parsing starting_count = MSG_GetNumBytesRead( msg ); // updates each frame @@ -2334,6 +2334,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ) cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart; break; case svc_changing: + old_background = cl.background; if( MSG_ReadOneBit( msg )) { cls.changelevel = true; @@ -2362,6 +2363,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ) // g-cont. local client skip the challenge if( SV_Active()) cls.state = ca_disconnected; else cls.state = ca_connecting; + cl.background = old_background; cls.connect_time = MAX_HEARTBEAT; } break; diff --git a/engine/client/cl_scrn.c b/engine/client/cl_scrn.c index d6c4cda6..b82528d1 100644 --- a/engine/client/cl_scrn.c +++ b/engine/client/cl_scrn.c @@ -319,7 +319,7 @@ void SCR_BeginLoadingPlaque( qboolean is_background ) if( cls.state == ca_disconnected || cls.disable_screen ) return; // already set - cls.draw_changelevel = is_background ? false : true; + cls.draw_changelevel = !is_background; SCR_UpdateScreen(); cls.disable_screen = host.realtime; cls.disable_servercount = cl.servercount; @@ -454,6 +454,7 @@ void SCR_UpdateScreen( void ) switch( cls.state ) { case ca_disconnected: + Con_RunConsole (); break; case ca_connecting: case ca_connected: @@ -461,6 +462,7 @@ void SCR_UpdateScreen( void ) SCR_DrawPlaque(); break; case ca_active: + Con_RunConsole (); V_RenderView(); break; case ca_cinematic: diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 662525d6..18ed1736 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -46,6 +46,48 @@ model_t *cl_sprite_ricochet = NULL; model_t *cl_sprite_shell = NULL; model_t *cl_sprite_glow = NULL; +const char *cl_default_sprites[] = +{ + // built-in sprites + "sprites/muzzleflash1.spr", + "sprites/muzzleflash2.spr", + "sprites/muzzleflash3.spr", + "sprites/dot.spr", + "sprites/animglow01.spr", + "sprites/richo1.spr", + "sprites/shellchrome.spr", +}; + +const char *cl_player_shell_sounds[] = +{ + "player/pl_shell1.wav", + "player/pl_shell2.wav", + "player/pl_shell3.wav", +}; + +const char *cl_weapon_shell_sounds[] = +{ + "weapons/sshell1.wav", + "weapons/sshell2.wav", + "weapons/sshell3.wav", +}; + +const char *cl_ricochet_sounds[] = +{ + "weapons/ric1.wav", + "weapons/ric2.wav", + "weapons/ric3.wav", + "weapons/ric4.wav", + "weapons/ric5.wav", +}; + +const char *cl_explode_sounds[] = +{ + "weapons/explode3.wav", + "weapons/explode4.wav", + "weapons/explode5.wav", +}; + /* ================ CL_LoadClientSprites @@ -55,14 +97,91 @@ INTERNAL RESOURCE */ void CL_LoadClientSprites( void ) { - cl_sprite_muzzleflash[0] = CL_LoadClientSprite( "sprites/muzzleflash1.spr" ); - cl_sprite_muzzleflash[1] = CL_LoadClientSprite( "sprites/muzzleflash2.spr" ); - cl_sprite_muzzleflash[2] = CL_LoadClientSprite( "sprites/muzzleflash3.spr" ); + cl_sprite_muzzleflash[0] = CL_LoadClientSprite( cl_default_sprites[0] ); + cl_sprite_muzzleflash[1] = CL_LoadClientSprite( cl_default_sprites[1] ); + cl_sprite_muzzleflash[2] = CL_LoadClientSprite( cl_default_sprites[2] ); - cl_sprite_dot = CL_LoadClientSprite( "sprites/dot.spr" ); - cl_sprite_glow = CL_LoadClientSprite( "sprites/animglow01.spr" ); - cl_sprite_ricochet = CL_LoadClientSprite( "sprites/richo1.spr" ); - cl_sprite_shell = CL_LoadClientSprite( "sprites/shellchrome.spr" ); + cl_sprite_dot = CL_LoadClientSprite( cl_default_sprites[3] ); + cl_sprite_glow = CL_LoadClientSprite( cl_default_sprites[4] ); + cl_sprite_ricochet = CL_LoadClientSprite( cl_default_sprites[5] ); + cl_sprite_shell = CL_LoadClientSprite( cl_default_sprites[6] ); +} + +/* +================ +CL_AddClientResource + +add client-side resource to list +================ +*/ +void CL_AddClientResource( const char *filename, int type ) +{ + resource_t *pResource; + + pResource = Mem_Alloc( cls.mempool, sizeof( resource_t )); + + Q_strncpy( pResource->szFileName, filename, sizeof( pResource->szFileName )); + pResource->type = type; + pResource->nIndex = -1; // client resource marker + pResource->nDownloadSize = 1; + pResource->ucFlags |= RES_WASMISSING; + + CL_AddToResourceList( pResource, &cl.resourcesneeded ); +} + +/* +================ +CL_AddClientResources + +client resources not precached by server +================ +*/ +void CL_AddClientResources( void ) +{ + char filepath[MAX_QPATH]; + int i; + + // check sprites first + for( i = 0; i < ARRAYSIZE( cl_default_sprites ); i++ ) + { + if( !FS_FileExists( cl_default_sprites[i], false )) + CL_AddClientResource( cl_default_sprites[i], t_model ); + } + + // then check sounds + for( i = 0; i < ARRAYSIZE( cl_player_shell_sounds ); i++ ) + { + Q_snprintf( filepath, sizeof( filepath ), "%s%s", DEFAULT_SOUNDPATH, cl_player_shell_sounds[i] ); + + if( !FS_FileExists( filepath, false )) + CL_AddClientResource( cl_player_shell_sounds[i], t_sound ); + } + + for( i = 0; i < ARRAYSIZE( cl_weapon_shell_sounds ); i++ ) + { + Q_snprintf( filepath, sizeof( filepath ), "%s%s", DEFAULT_SOUNDPATH, cl_weapon_shell_sounds[i] ); + + if( !FS_FileExists( filepath, false )) + CL_AddClientResource( cl_weapon_shell_sounds[i], t_sound ); + } + + for( i = 0; i < ARRAYSIZE( cl_explode_sounds ); i++ ) + { + Q_snprintf( filepath, sizeof( filepath ), "%s%s", DEFAULT_SOUNDPATH, cl_explode_sounds[i] ); + + if( !FS_FileExists( filepath, false )) + CL_AddClientResource( cl_explode_sounds[i], t_sound ); + } + +#if 0 // ric sounds was precached by server-side + for( i = 0; i < ARRAYSIZE( cl_ricochet_sounds ); i++ ) + { + Q_snprintf( filepath, sizeof( filepath ), "%s%s", DEFAULT_SOUNDPATH, cl_ricochet_sounds[i] ); + + if( !FS_FileExists( filepath, false )) + CL_AddClientResource( cl_ricochet_sounds[i], t_sound ); + } +#endif } /* @@ -311,15 +430,15 @@ void CL_TempEntPlaySound( TEMPENTITY *pTemp, float damp ) Q_snprintf( soundname, sizeof( soundname ), "debris/wood%i.wav", COM_RandomLong( 1, 4 )); break; case BOUNCE_SHRAP: - Q_snprintf( soundname, sizeof( soundname ), "weapons/ric%i.wav", COM_RandomLong( 1, 5 )); + Q_snprintf( soundname, sizeof( soundname ), "%s", cl_ricochet_sounds[COM_RandomLong( 0, 4 )] ); break; case BOUNCE_SHOTSHELL: - Q_snprintf( soundname, sizeof( soundname ), "weapons/sshell%i.wav", COM_RandomLong( 1, 3 )); + Q_snprintf( soundname, sizeof( soundname ), "%s", cl_weapon_shell_sounds[COM_RandomLong( 0, 2 )] ); isshellcasing = true; // shell casings have different playback parameters fvol = 0.5f; break; case BOUNCE_SHELL: - Q_snprintf( soundname, sizeof( soundname ), "player/pl_shell%i.wav", COM_RandomLong( 1, 3 )); + Q_snprintf( soundname, sizeof( soundname ), "%s", cl_player_shell_sounds[COM_RandomLong( 0, 2 )] ); isshellcasing = true; // shell casings have different playback parameters break; case BOUNCE_CONCRETE: @@ -1518,7 +1637,7 @@ void R_RicochetSound( const vec3_t pos ) char soundpath[32]; sound_t handle; - Q_snprintf( soundpath, sizeof( soundpath ), "weapons/ric%i.wav", COM_RandomLong( 1, 5 )); + Q_snprintf( soundpath, sizeof( soundpath ), "%s", cl_ricochet_sounds[COM_RandomLong( 0, 4 )] ); handle = S_RegisterSound( soundpath ); S_StartSound( pos, 0, CHAN_AUTO, handle, fvol, ATTN_NORM, iPitch, 0 ); @@ -1668,7 +1787,7 @@ void R_Explosion( vec3_t pos, int model, float scale, float framerate, int flags if( !FBitSet( flags, TE_EXPLFLAG_NOSOUND )) { - hSound = S_RegisterSound( va( "weapons/explode%i.wav", COM_RandomLong( 3, 5 ))); + hSound = S_RegisterSound( va( "%s", cl_explode_sounds[COM_RandomLong( 0, 3 )] )); S_StartSound( pos, 0, CHAN_STATIC, hSound, VOL_NORM, 0.3f, PITCH_NORM, 0 ); } } diff --git a/engine/client/client.h b/engine/client/client.h index ea1ee11c..54b24f2e 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -702,9 +702,6 @@ void CL_DecayLights( void ); //================================================= -void CL_PrepVideo( void ); -void CL_PrepSound( void ); - // // cl_cmds.c // @@ -939,6 +936,7 @@ void CL_FireCustomDecal( int textureIndex, int entityIndex, int modelIndex, floa void CL_DecalShoot( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags ); void CL_PlayerDecal( int textureIndex, int entityIndex, float *pos ); void R_FreeDeadParticles( struct particle_s **ppparticles ); +void CL_AddClientResources( void ); int CL_FxBlend( cl_entity_t *e ); void CL_InitParticles( void ); void CL_ClearParticles( void ); diff --git a/engine/common/common.h b/engine/common/common.h index af1d09a2..64ac808b 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -338,6 +338,7 @@ typedef struct host_parm_s byte *mempool; // static mempool for misc allocations string finalmsg; // server shutdown final message string downloadfile; // filename to be downloading + int downloadcount; // how many files remain to downloading host_redirect_t rd; // remote console // command line parms @@ -699,7 +700,7 @@ void COM_InitHostState( void ); void COM_NewGame( char const *pMapName ); void COM_LoadLevel( char const *pMapName, qboolean background ); void COM_LoadGame( char const *pSaveFileName ); -void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName ); +void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName, qboolean background ); void COM_Frame( float time ); /* diff --git a/engine/common/console.c b/engine/common/console.c index edc15600..e7245a91 100644 --- a/engine/common/console.c +++ b/engine/common/console.c @@ -1902,19 +1902,23 @@ Draws the debug messages (not passed to console history) */ void Con_DrawDebug( void ) { - int x, y, stringLen; - string dlstring; - int charH; + static double timeStart; + string dlstring; + int x, y; if( scr_download->value != -1.0f ) { - Q_snprintf( dlstring, sizeof( dlstring ), "Downloading: ^2%s^7 ", host.downloadfile ); - Con_DrawStringLen( dlstring, &stringLen, &charH ); - Q_snprintf( dlstring, sizeof( dlstring ), "Downloading: ^2%s^7 %5.1f%%", host.downloadfile, scr_download->value ); - x = glState.width - stringLen; - y = charH * 1.05f; + Q_snprintf( dlstring, sizeof( dlstring ), "Downloading [%d remaining]: ^2%s^7 %5.1f%%", + host.downloadcount, host.downloadfile, scr_download->value, Sys_DoubleTime() - timeStart ); + x = glState.width - 400; + y = con.curFont->charHeight * 1.05f; Con_DrawString( x, y, dlstring, g_color_table[7] ); } + else + { + timeStart = Sys_DoubleTime(); + } + if( !host_developer.value || Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" )) return; @@ -2241,10 +2245,6 @@ void Con_RunConsole( void ) } else con.showlines = 0; // none visible - // HACKHACK: don't accumulate frametime - if( cls.state < ca_active || cl.first_frame ) - host.realframetime = 0.0f; - lines_per_frame = fabs( scr_conspeed->value ) * host.realframetime; if( con.showlines < con.vislines ) diff --git a/engine/common/filesystem.c b/engine/common/filesystem.c index 2f8e4b62..d0a5781a 100644 --- a/engine/common/filesystem.c +++ b/engine/common/filesystem.c @@ -2381,9 +2381,9 @@ return size of file in bytes */ long FS_FileSize( const char *filename, qboolean gamedironly ) { - file_t *fp; int length = -1; // in case file was missed - + file_t *fp; + fp = FS_Open( filename, "rb", gamedironly ); if( fp ) diff --git a/engine/common/host_state.c b/engine/common/host_state.c index 9a819418..a61d94cf 100644 --- a/engine/common/host_state.c +++ b/engine/common/host_state.c @@ -73,12 +73,13 @@ void COM_LoadGame( char const *pMapName ) GameState->loadGame = true; } -void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName ) +void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName, qboolean background ) { if( GameState->nextstate != STATE_RUNFRAME ) return; Q_strncpy( GameState->levelName, pNewLevel, sizeof( GameState->levelName )); + GameState->backgroundMap = background; if( COM_CheckString( pLandmarkName )) { @@ -128,7 +129,7 @@ void Host_RunFrame( float time ) Host_SetState( STATE_GAME_SHUTDOWN, false ); break; case STATE_CHANGELEVEL: - SCR_BeginLoadingPlaque( false ); + SCR_BeginLoadingPlaque( GameState->backgroundMap ); Host_SetState( GameState->nextstate, true ); break; default: diff --git a/engine/common/mod_local.h b/engine/common/mod_local.h index 41d7fa9d..ba7b6137 100644 --- a/engine/common/mod_local.h +++ b/engine/common/mod_local.h @@ -178,6 +178,7 @@ void Mod_PrintWorldStats_f( void ); void Mod_InitStudioAPI( void ); void Mod_InitStudioHull( void ); void Mod_ResetStudioAPI( void ); +const char *Mod_StudioTexName( const char *modname ); qboolean Mod_GetStudioBounds( const char *name, vec3_t mins, vec3_t maxs ); void Mod_StudioGetAttachment( const edict_t *e, int iAttachment, float *org, float *ang ); void Mod_GetBonePosition( const edict_t *e, int iBone, float *org, float *ang ); diff --git a/engine/common/mod_studio.c b/engine/common/mod_studio.c index eb5b8341..ba44e8b5 100644 --- a/engine/common/mod_studio.c +++ b/engine/common/mod_studio.c @@ -727,11 +727,11 @@ Mod_StudioTexName extract texture filename from modelname =============== */ -const char *Mod_StudioTexName( model_t *mod ) +const char *Mod_StudioTexName( const char *modname ) { static char texname[MAX_QPATH]; - Q_strncpy( texname, mod->name, sizeof( texname )); + Q_strncpy( texname, modname, sizeof( texname )); COM_StripExtension( texname ); Q_strncat( texname, "T.mdl", sizeof( texname )); @@ -813,7 +813,7 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded ) void *buffer2 = NULL; size_t size1, size2; - buffer2 = FS_LoadFile( Mod_StudioTexName( mod ), NULL, false ); + buffer2 = FS_LoadFile( Mod_StudioTexName( mod->name ), NULL, false ); thdr = R_StudioLoadHeader( mod, buffer2 ); if( !thdr ) diff --git a/engine/common/net_buffer.c b/engine/common/net_buffer.c index 79d86c70..1b14f6d2 100644 --- a/engine/common/net_buffer.c +++ b/engine/common/net_buffer.c @@ -54,9 +54,9 @@ void MSG_InitMasks( void ) void MSG_InitExt( sizebuf_t *sb, const char *pDebugName, void *pData, int nBytes, int nMaxBits ) { - sb->pDebugName = pDebugName; - MSG_StartWriting( sb, pData, nBytes, 0, nMaxBits ); + + sb->pDebugName = pDebugName; } void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, int nBits ) @@ -64,6 +64,7 @@ void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, in // make sure it's dword aligned and padded. Assert(((dword)pData & 3 ) == 0 ); + sb->pDebugName = "Unnamed"; sb->pData = (byte *)pData; if( nBits == -1 ) @@ -654,7 +655,7 @@ void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove ) int remaining_to_end = sb->nDataBits - endbit; sizebuf_t temp; - MSG_StartWriting( &temp, sb->pData, sb->nDataBits << 3, startbit, -1 ); + MSG_StartWriting( &temp, sb->pData, MSG_GetMaxBytes( sb ), startbit, -1 ); MSG_SeekToBit( sb, endbit ); for( i = 0; i < remaining_to_end; i++ ) diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 6ed814c0..bf10ab54 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -28,8 +28,10 @@ GNU General Public License for more details. #define FLOW_AVG ( 2.0 / 3.0 ) // how fast to converge flow estimates #define FLOW_INTERVAL 0.1 // don't compute more often than this -#define MAX_RELIABLE_PAYLOAD 1200 // biggest packet that has frag and or reliable data -#define MAX_RESEND_PAYLOAD 1400 +#define MAX_RELIABLE_PAYLOAD 32768 // biggest packet that has frag and or reliable data +#define MAX_RELIABLE_PAYLOAD_BITS (MAX_RELIABLE_PAYLOAD<<3) +#define MAX_RESEND_PAYLOAD 36000 +#define MAX_RESEND_PAYLOAD_BITS (MAX_RESEND_PAYLOAD<<3) // forward declarations void Netchan_FlushIncoming( netchan_t *chan, int stream ); @@ -502,7 +504,7 @@ void Netchan_FragSend( netchan_t *chan ) // already something queued up, just leave in waitlist if( chan->fragbufs[i] ) continue; - wait = chan->waitlist[i] ; + wait = chan->waitlist[i]; // nothing to queue? if( !wait ) continue; @@ -587,6 +589,8 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg ) chunksize = chan->pfnBlockSize( chan->client ); else chunksize = FRAGMENT_SV2CL_MAX_SIZE; +chunksize = 8192; + wait = (fragbufwaiting_t *)Mem_Alloc( net_mempool, sizeof( fragbufwaiting_t )); remaining = MSG_GetNumBitsWritten( msg ); @@ -609,8 +613,8 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg ) MSG_StartReading( &temp, MSG_GetData( msg ), MSG_GetMaxBytes( msg ), MSG_GetNumBitsWritten( msg ), -1 ); MSG_SeekToBit( &temp, pos ); - MSG_ReadBits( &temp, buffer, bits ); + MSG_ReadBits( &temp, buffer, bits ); MSG_WriteBits( &buf->frag_message, buffer, bits ); Netchan_AddFragbufToTail( wait, buf ); @@ -718,8 +722,8 @@ void Netchan_CheckForCompletion( netchan_t *chan, int stream, int intotalbuffers // received final message if( c == intotalbuffers ) { +// MsgDev( D_NOTE, "\n%s: incoming is complete %i bytes waiting\n", ns_strings[chan->sock], size ); chan->incomingready[stream] = true; - MsgDev( D_NOTE, "\n%s: incoming is complete %i bytes waiting\n", ns_strings[chan->sock], size ); } } @@ -822,7 +826,7 @@ int Netchan_CreateFileFragments( netchan_t *chan, const char *filename ) chunksize = chan->pfnBlockSize( chan->client ); else chunksize = FRAGMENT_SV2CL_MAX_SIZE; filesize = FS_FileSize( filename, false ); - +chunksize = 32768; if( filesize <= 0 ) { MsgDev( D_WARN, "Unable to open %s for transfer\n", filename ); @@ -1092,7 +1096,6 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg ) else { // g-cont. it's will be stored downloaded files directly into game folder - Con_Printf( "write file: %s\n", filename ); FS_WriteFile( filename, buffer, pos ); Mem_Free( buffer ); } @@ -1113,6 +1116,8 @@ qboolean Netchan_Validate( netchan_t *chan, sizebuf_t *sb, qboolean *frag_messag int i, buffer, offset; int count, length; +return true; + for( i = 0; i < MAX_STREAMS; i++ ) { if( !frag_message[i] ) @@ -1152,8 +1157,11 @@ void Netchan_UpdateProgress( netchan_t *chan ) int total = 0; float bestpercent = 0.0; - scr_download->value = -1.0f; - host.downloadfile[0] = '\0'; + if( host.downloadcount == 0 ) + { + scr_download->value = -1.0f; + host.downloadfile[0] = '\0'; + } // do show slider for file downloads. if( !chan->incomingbufs[FRAG_FILE_STREAM] ) @@ -1295,7 +1303,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data ) send_from_regular = false; // if the reliable buffer has gotten too big, queue it at the end of everything and clear out buffer - if( MSG_GetNumBytesWritten( &chan->message ) > MAX_RELIABLE_PAYLOAD ) + if( MSG_GetNumBitsWritten( &chan->message ) > MAX_RELIABLE_PAYLOAD_BITS ) { Netchan_CreateFragments_( chan, &chan->message ); MSG_Clear( &chan->message ); @@ -1345,7 +1353,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data ) if( pbuf ) { - fragment_size = MSG_GetNumBytesWritten( &pbuf->frag_message ); + fragment_size = MSG_GetNumBitsWritten( &pbuf->frag_message ); // files set size a bit differently. if( pbuf->isfile && !pbuf->isbuffer ) @@ -1355,7 +1363,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data ) } // make sure we have enought space left - if( send_from_frag[i] && pbuf && (( chan->reliable_length + fragment_size ) < MAX_RELIABLE_PAYLOAD )) + if( send_from_frag[i] && pbuf && (( chan->reliable_length + fragment_size ) < MAX_RELIABLE_PAYLOAD_BITS )) { sizebuf_t temp; @@ -1451,7 +1459,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data ) } // is there room for the unreliable payload? - max_send_size = (MAX_RESEND_PAYLOAD << 3); + max_send_size = MAX_RESEND_PAYLOAD_BITS; if( !send_resending ) max_send_size = MSG_GetMaxBits( &send ); @@ -1462,8 +1470,6 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data ) // deal with packets that are too small for some networks if( MSG_GetNumBytesWritten( &send ) < 16 && !NET_IsLocalAddress( chan->remote_address )) // packet too small for some networks { - int i; - // go ahead and pad a full 16 extra bytes -- this only happens during authentication / signon for( i = MSG_GetNumBytesWritten( &send ); i < 16; i++ ) { diff --git a/engine/common/net_ws.c b/engine/common/net_ws.c index d36c158a..8e7337a1 100644 --- a/engine/common/net_ws.c +++ b/engine/common/net_ws.c @@ -18,17 +18,22 @@ GNU General Public License for more details. #include "netchan.h" #include "mathlib.h" -#define PORT_ANY -1 +//#define NET_USE_FRAGMENTS // disabled until revision of netchan will be done +#define PORT_ANY -1 #define MAX_LOOPBACK 4 #define MASK_LOOPBACK (MAX_LOOPBACK - 1) #define MAX_ROUTEABLE_PACKET 1400 #define SPLIT_SIZE ( MAX_ROUTEABLE_PACKET - sizeof( SPLITPACKET )) - -#define MAX_UDP_PACKET 4010 // 9 bytes SPLITHEADER + 4000 payload? #define NET_MAX_FRAGMENTS 32 +#ifdef NET_USE_FRAGMENTS +#define MAX_UDP_PACKET 4010 // 9 bytes SPLITHEADER + 4000 payload? +#else +#define MAX_UDP_PACKET NET_MAX_MESSAGE +#endif + // wsock32.dll exports static int (_stdcall *pWSACleanup)( void ); static word (_stdcall *pNtohs)( word netshort ); @@ -84,7 +89,7 @@ dll_info_t winsock_dll = { "wsock32.dll", winsock_funcs, false }; typedef struct { - byte data[NET_MAX_MESSAGE]; + byte data[MAX_INIT_MSG]; int datalen; } net_loopmsg_t; @@ -977,6 +982,7 @@ Fragment long packets, send short directly */ int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, int len, int flags, const struct sockaddr *to, int tolen ) { +#ifdef NET_USE_FRAGMENTS // do we need to break this packet up? if( sock == NS_SERVER && len > MAX_ROUTEABLE_PACKET ) { @@ -1029,6 +1035,9 @@ int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, int len, int f // no fragmenantion for client connection return pSendTo( net_socket, buf, len, flags, to, tolen ); } +#else + return pSendTo( net_socket, buf, len, flags, to, tolen ); +#endif } /* diff --git a/engine/common/net_ws.h b/engine/common/net_ws.h index 5fc09e10..49e31c59 100644 --- a/engine/common/net_ws.h +++ b/engine/common/net_ws.h @@ -23,6 +23,14 @@ typedef enum NS_COUNT } netsrc_t; +// Max length of unreliable message +#define MAX_DATAGRAM 4000 + +// Max length of a multicast message +#define MAX_MULTICAST 8192 // some mods spamming for rain effect + +#define MAX_INIT_MSG 0x20000 // max length of possible message + #include "netadr.h" extern convar_t *net_showpackets; diff --git a/engine/common/netchan.h b/engine/common/netchan.h index fcddbd31..44630efc 100644 --- a/engine/common/netchan.h +++ b/engine/common/netchan.h @@ -37,16 +37,8 @@ GNU General Public License for more details. // NETWORKING INFO -// Max length of a multicast message -#define MAX_MULTICAST 8192 // some mods spamming for rain effect - -// Max length of unreliable message -#define MAX_DATAGRAM 4000 - -#define MAX_INIT_MSG 0x20000 // max length of possible message - // This is the packet payload without any header bytes (which are attached for actual sending) -#define NET_MAX_PAYLOAD 3990 +#define NET_MAX_PAYLOAD MAX_INIT_MSG // This is the payload plus any header info (excluding UDP header) @@ -122,7 +114,7 @@ typedef struct fragbuf_s struct fragbuf_s *next; // next buffer in chain int bufferid; // id of this buffer sizebuf_t frag_message; // message buffer where raw data is stored - byte frag_message_buf[NET_MAX_PAYLOAD]; // the actual data sits here + byte frag_message_buf[NET_MAX_MESSAGE]; // the actual data sits here qboolean isfile; // is this a file buffer? qboolean isbuffer; // is this file buffer from memory ( custom decal, etc. ). char filename[MAX_OSPATH]; // name of the file to save out on remote host @@ -165,12 +157,12 @@ typedef struct netchan_s // staging and holding areas sizebuf_t message; - byte message_buf[NET_MAX_PAYLOAD]; + byte message_buf[NET_MAX_MESSAGE]; // reliable message buffer. // we keep adding to it until reliable is acknowledged. Then we clear it. int reliable_length; - byte reliable_buf[NET_MAX_PAYLOAD]; // unacked reliable message (max size for loopback connection) + byte reliable_buf[NET_MAX_MESSAGE]; // unacked reliable message (max size for loopback connection) // Waiting list of buffered fragments to go onto queue. // Multiple outgoing buffers can be queued in succession @@ -182,8 +174,8 @@ typedef struct netchan_s fragbuf_t *fragbufs[MAX_STREAMS]; // the current fragment being set int fragbufcount[MAX_STREAMS]; // the total number of fragments in this stream - short frag_startpos[MAX_STREAMS]; // position in outgoing buffer where frag data starts - short frag_length[MAX_STREAMS]; // length of frag data in the buffer + int frag_startpos[MAX_STREAMS]; // position in outgoing buffer where frag data starts + int frag_length[MAX_STREAMS]; // length of frag data in the buffer fragbuf_t *incomingbufs[MAX_STREAMS]; // incoming fragments are stored here qboolean incomingready[MAX_STREAMS]; // set to true when incoming data is ready diff --git a/engine/server/server.h b/engine/server/server.h index b4188984..b398520c 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -652,7 +652,7 @@ void SV_ClearSaveDir( void ); void SV_SaveGame( const char *pName ); qboolean SV_LoadGame( const char *pName ); int SV_LoadGameState( char const *level, qboolean changelevel ); -void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char *start ); +void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char *start, qboolean background ); void SV_LoadAdjacentEnts( const char *pOldLevel, const char *pLandmarkName ); const char *SV_GetLatestSave( void ); void SV_InitSaveRestore( void ); diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index 70233961..6480b913 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -1488,138 +1488,6 @@ static qboolean SV_New_f( sv_client_t *cl ) return true; } -/* -================== -SV_WriteModels_f -================== -*/ -static qboolean SV_WriteModels_f( sv_client_t *cl ) -{ - int start; - string cmd; - - if( cl->state != cs_connected ) - return false; - - // handle the case of a level changing while a client was connecting - if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount ) - { - SV_New_f( cl ); - return true; - } - - start = Q_atoi( Cmd_Argv( 2 )); - - // write a packet full of data - while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_DATAGRAM ) && start < MAX_MODELS ) - { - if( sv.model_precache[start][0] ) - { - MSG_BeginServerCmd( &cl->netchan.message, svc_modelindex ); - MSG_WriteUBitLong( &cl->netchan.message, start, MAX_MODEL_BITS ); - MSG_WriteString( &cl->netchan.message, sv.model_precache[start] ); - } - start++; - } - - if( start == MAX_MODELS ) Q_snprintf( cmd, MAX_STRING, "cmd soundlist %i %i\n", svs.spawncount, 0 ); - else Q_snprintf( cmd, MAX_STRING, "cmd modellist %i %i\n", svs.spawncount, start ); - - // send next command - MSG_BeginServerCmd( &cl->netchan.message, svc_stufftext ); - MSG_WriteString( &cl->netchan.message, cmd ); - - return true; -} - -/* -================== -SV_WriteSounds_f -================== -*/ -static qboolean SV_WriteSounds_f( sv_client_t *cl ) -{ - int start; - string cmd; - - if( cl->state != cs_connected ) - return false; - - // handle the case of a level changing while a client was connecting - if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount ) - { - SV_New_f( cl ); - return true; - } - - start = Q_atoi( Cmd_Argv( 2 )); - - // write a packet full of data - while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_DATAGRAM ) && start < MAX_SOUNDS ) - { - if( sv.sound_precache[start][0] ) - { - MSG_BeginServerCmd( &cl->netchan.message, svc_soundindex ); - MSG_WriteUBitLong( &cl->netchan.message, start, MAX_SOUND_BITS ); - MSG_WriteString( &cl->netchan.message, sv.sound_precache[start] ); - } - start++; - } - - if( start == MAX_SOUNDS ) Q_snprintf( cmd, MAX_STRING, "cmd eventlist %i %i\n", svs.spawncount, 0 ); - else Q_snprintf( cmd, MAX_STRING, "cmd soundlist %i %i\n", svs.spawncount, start ); - - // send next command - MSG_BeginServerCmd( &cl->netchan.message, svc_stufftext ); - MSG_WriteString( &cl->netchan.message, cmd ); - - return true; -} - -/* -================== -SV_WriteEvents_f -================== -*/ -static qboolean SV_WriteEvents_f( sv_client_t *cl ) -{ - int start; - string cmd; - - if( cl->state != cs_connected ) - return false; - - // handle the case of a level changing while a client was connecting - if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount ) - { - SV_New_f( cl ); - return true; - } - - start = Q_atoi( Cmd_Argv( 2 )); - - // write a packet full of data - while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_DATAGRAM ) && start < MAX_EVENTS ) - { - if( sv.event_precache[start][0] ) - { - MSG_BeginServerCmd( &cl->netchan.message, svc_eventindex ); - MSG_WriteUBitLong( &cl->netchan.message, start, MAX_EVENT_BITS ); - MSG_WriteString( &cl->netchan.message, sv.event_precache[start] ); - } - start++; - } - - if( start == MAX_EVENTS ) Q_snprintf( cmd, MAX_STRING, "precache %i\n", svs.spawncount ); - else Q_snprintf( cmd, MAX_STRING, "cmd eventlist %i %i\n", svs.spawncount, start ); - - // send next command - MSG_BeginServerCmd( &cl->netchan.message, svc_stufftext ); - MSG_WriteString( &cl->netchan.message, cmd ); - - return true; -} - /* ================= SV_Disconnect_f @@ -1951,6 +1819,13 @@ static qboolean SV_DownloadFile_f( sv_client_t *cl ) { if( Netchan_CreateFileFragments( &cl->netchan, name )) { + // also check the model textures + if( !Q_stricmp( COM_FileExtension( name ), "mdl" )) + { + if( FS_FileExists( Mod_StudioTexName( name ), false ) > 0 ) + Netchan_CreateFileFragments( &cl->netchan, Mod_StudioTexName( name )); + } + Netchan_FragSend( &cl->netchan ); return true; } @@ -2050,9 +1925,6 @@ ucmd_t ucmds[] = { "notarget", SV_Notarget_f }, { "info", SV_ShowServerinfo_f }, { "dlfile", SV_DownloadFile_f }, -{ "modellist", SV_WriteModels_f }, -{ "soundlist", SV_WriteSounds_f }, -{ "eventlist", SV_WriteEvents_f }, { "disconnect", SV_Disconnect_f }, { "userinfo", SV_UpdateUserinfo_f }, { NULL, NULL } diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index 6f85a202..33167ed9 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -1350,8 +1350,8 @@ void pfnChangeLevel( const char *level, const char *landmark ) SV_SkipUpdates (); // changelevel will be executed on a next frame - if( smooth ) COM_ChangeLevel( mapname, landname ); // Smoothed Half-Life changelevel - else COM_ChangeLevel( mapname, NULL ); // Classic Quake changlevel + if( smooth ) COM_ChangeLevel( mapname, landname, sv.background ); // Smoothed Half-Life changelevel + else COM_ChangeLevel( mapname, NULL, sv.background ); // Classic Quake changlevel } /* diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 3ae4f5e7..bef9fdcd 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -279,8 +279,7 @@ void SV_CreateResourceList( void ) { s = sv.files_precache[i]; if( !COM_CheckString( s )) break; // end of list - nSize = ( svs.maxclients > 1 ) ? FS_FileSize( s, false ) : 0; - if( nSize < 0 ) nSize = 0; + nSize = FS_FileSize( s, false ); SV_AddResource( t_generic, s, nSize, RES_FATALIFMISSING, i ); } @@ -300,8 +299,7 @@ void SV_CreateResourceList( void ) } else { - nSize = ( svs.maxclients > 1 ) ? FS_FileSize( va( "sound/%s", s ), false ) : 0; - if( nSize < 0 ) nSize = 0; + nSize = FS_FileSize( va( "sound/%s", s ), false ); SV_AddResource( t_sound, s, nSize, 0, i ); } } @@ -310,8 +308,7 @@ void SV_CreateResourceList( void ) { s = sv.model_precache[i]; if( !COM_CheckString( s )) break; // end of list - nSize = ( svs.maxclients > 1 && s[0] != '*' ) ? FS_FileSize( s, false ) : 0; - if( nSize < 0 ) nSize = 0; + nSize = ( s[0] != '*' ) ? FS_FileSize( s, false ) : 0; SV_AddResource( t_model, s, nSize, sv.model_precache_flags[i], i ); } @@ -325,8 +322,7 @@ void SV_CreateResourceList( void ) { s = sv.event_precache[i]; if( !COM_CheckString( s )) break; // end of list - nSize = ( svs.maxclients > 1 ) ? FS_FileSize( s, false ) : 0; - if( nSize < 0 ) nSize = 0; + nSize = FS_FileSize( s, false ); SV_AddResource( t_eventscript, s, nSize, RES_FATALIFMISSING, i ); } } @@ -908,5 +904,5 @@ State machine exec changelevel path */ void SV_ExecChangeLevel( void ) { - SV_ChangeLevel( GameState->loadGame, GameState->levelName, GameState->landmarkName ); + SV_ChangeLevel( GameState->loadGame, GameState->levelName, GameState->landmarkName, GameState->backgroundMap ); } \ No newline at end of file diff --git a/engine/server/sv_pmove.c b/engine/server/sv_pmove.c index 9d880bd3..f04aa84c 100644 --- a/engine/server/sv_pmove.c +++ b/engine/server/sv_pmove.c @@ -32,9 +32,6 @@ void SV_ClearPhysEnts( void ) qboolean SV_PlayerIsFrozen( edict_t *pClient ) { - if( sv.background ) - return true; // always freeze client on background - if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE )) return false; diff --git a/engine/server/sv_save.c b/engine/server/sv_save.c index f640a2e1..cfb41a70 100644 --- a/engine/server/sv_save.c +++ b/engine/server/sv_save.c @@ -1922,7 +1922,7 @@ void SV_LoadAdjacentEnts( const char *pOldLevel, const char *pLandmarkName ) SV_ChangeLevel ============= */ -void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char *start ) +void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char *start, qboolean background ) { char level[MAX_QPATH]; char oldlevel[MAX_QPATH]; @@ -1958,7 +1958,7 @@ void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char SV_FinalMessage( "", true ); SV_DeactivateServer (); - if( !SV_SpawnServer( level, startspot, false )) + if( !SV_SpawnServer( level, startspot, background )) return; // ??? if( loadfromsavedgame )