From f9c1a60dfdb52494e07385f84747c7480c79ec90 Mon Sep 17 00:00:00 2001 From: g-cont Date: Mon, 5 Mar 2018 00:00:00 +0300 Subject: [PATCH] 05 Mar 2018 --- common/render_api.h | 2 + engine/client/cl_demo.c | 3 - engine/client/cl_frame.c | 37 +++++++-- engine/client/cl_main.c | 14 ++-- engine/client/cl_parse.c | 155 ++++++++++++++++++++---------------- engine/client/cl_scrn.c | 4 +- engine/client/cl_tent.c | 8 +- engine/client/cl_video.c | 2 +- engine/client/cl_view.c | 2 +- engine/client/client.h | 4 +- engine/client/gl_image.c | 3 +- engine/client/gl_refrag.c | 25 +----- engine/client/gl_rmisc.c | 26 ++++++ engine/common/console.c | 6 +- engine/common/host.c | 2 +- engine/common/host_state.c | 2 + engine/common/mod_bmodel.c | 33 +++++--- engine/common/mod_local.h | 1 - engine/common/protocol.h | 2 +- engine/common/zone.c | 10 ++- engine/server/server.h | 5 +- engine/server/sv_client.c | 84 ++++++++++--------- engine/server/sv_custom.c | 6 ++ engine/server/sv_frame.c | 2 +- engine/server/sv_game.c | 2 +- engine/server/sv_init.c | 45 +++-------- engine/server/sv_main.c | 47 ++++++----- engine/server/sv_phys.c | 4 +- engine/server/sv_save.c | 7 +- mainui/extdll.h | 3 + mainui/menu_playersetup.cpp | 17 ++-- xash.dsw | 12 --- 32 files changed, 318 insertions(+), 257 deletions(-) diff --git a/common/render_api.h b/common/render_api.h index 19a1aa0f..46c13526 100644 --- a/common/render_api.h +++ b/common/render_api.h @@ -261,6 +261,8 @@ typedef struct render_interface_s byte* (*Mod_GetCurrentVis)( void ); // tell the renderer what new map is started void (*R_NewMap)( void ); + // clear the render entities before each frame + void (*R_ClearScene)( void ); } render_interface_t; #endif//RENDER_API_H \ No newline at end of file diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index e52e829e..f792a6d0 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -447,9 +447,6 @@ void CL_StopRecord( void ) CL_WriteDemoCmdHeader( dem_stop, cls.demofile ); stoptime = CL_GetDemoRecordClock(); - - // close down the hud for now. - // g-cont. is this need??? if( clgame.hInstance ) clgame.dllFuncs.pfnReset(); curpos = FS_Tell( cls.demofile ); diff --git a/engine/client/cl_frame.c b/engine/client/cl_frame.c index ae617cab..3cf2b473 100644 --- a/engine/client/cl_frame.c +++ b/engine/client/cl_frame.c @@ -906,9 +906,12 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType ) return false; } - // don't add the player in firstperson mode - if( RP_LOCALCLIENT( ent ) && !CL_IsThirdPerson( ) && ( ent->index == cl.viewentity )) - return false; + if( FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP )) + { + // don't add the player in firstperson mode + if( RP_LOCALCLIENT( ent ) && !CL_IsThirdPerson( ) && ( ent->index == cl.viewentity )) + return false; + } if( entityType == ET_BEAM ) { @@ -987,6 +990,13 @@ void CL_LinkPlayers( frame_t *frame ) if( state->messagenum != cl.parsecount ) continue; // not present this frame + if( !FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP )) + { + // don't add the player in firstperson mode + if( !CL_IsThirdPerson( ) && ( i == cl.viewentity - 1 )) + continue; + } + if( !state->modelindex || FBitSet( state->effects, EF_NODRAW )) continue; @@ -1196,6 +1206,22 @@ void CL_LinkPacketEntities( frame_t *frame ) } } +/* +=============== +CL_MoveThirdpersonCamera + +think thirdperson +=============== +*/ +void CL_MoveThirdpersonCamera( void ) +{ + if( cls.state == ca_disconnected || cls.state == ca_cinematic ) + return; + + // think thirdperson camera + clgame.dllFuncs.CAM_Think (); +} + /* =============== CL_EmitEntities @@ -1224,8 +1250,9 @@ void CL_EmitEntities( void ) // set client ideal pitch when mlook is disabled CL_SetIdealPitch (); - // think thirdperson camera - clgame.dllFuncs.CAM_Think (); + // clear the scene befor start new frame + if( clgame.drawFuncs.R_ClearScene != NULL ) + clgame.drawFuncs.R_ClearScene(); // link all the visible clients first CL_LinkPlayers ( &cl.frames[cl.parsecountmod] ); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 53432d1b..653410a4 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -192,12 +192,12 @@ An svc_signonnum has been received, perform a client side setup */ void CL_SignonReply( void ) { - Con_Printf( "CL_SignonReply: %i\n", cls.signon ); + // g-cont. my favorite message :-) + Con_DPrintf( "CL_SignonReply: %i\n", cls.signon ); switch( cls.signon ) { case 1: - // g-cont. my favorite message :-) CL_ServerCommand( true, "begin" ); if( host_developer.value >= DEV_EXTENDED ) Mem_PrintStats(); @@ -604,7 +604,7 @@ void CL_CreateCmd( void ) CL_ApplyAddAngle(); } - active = ( cls.state == ca_active && !cl.paused && !cls.demoplayback ); + active = (( cls.signon == SIGNONS ) && !cl.paused && !cls.demoplayback ); clgame.dllFuncs.CL_CreateMove( host.frametime, &pcmd->cmd, active ); CL_PopPMStates(); @@ -2323,7 +2323,6 @@ void CL_InitLocal( void ) // these two added to shut up CS 1.5 about 'unknown' commands Cvar_Get( "lightgamma", "1", FCVAR_ARCHIVE, "ambient lighting level (legacy, unused)" ); Cvar_Get( "direct", "1", FCVAR_ARCHIVE, "direct lighting level (legacy, unused)" ); - Cvar_Get( "voice_serverdebug", "0", 0, "debug voice (legacy, unused)" ); // server commands Cmd_AddCommand ("noclip", NULL, "enable or disable no clipping mode" ); @@ -2472,6 +2471,7 @@ void Host_ClientFrame( void ) // a new portion updates from server CL_RedoPrediction (); + // TODO: implement // Voice_Idle( host.frametime ); // emit visible entities @@ -2480,9 +2480,11 @@ void Host_ClientFrame( void ) // in case we lost connection CL_CheckForResend (); -// while( CL_RequestMissingResources( )); + // procssing resources on handle + while( CL_RequestMissingResources( )); -// CL_HTTPUpdate (); + // handle thirdperson camera + CL_MoveThirdpersonCamera(); // handle spectator movement CL_MoveSpectatorCamera(); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 6d483683..4743a2e5 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -33,7 +33,7 @@ const char *svc_strings[svc_lastmsg+1] = "svc_nop", "svc_disconnect", "svc_event", - "svc_version", + "svc_changing", "svc_setview", "svc_sound", "svc_time", @@ -642,6 +642,34 @@ void CL_ParseSoundFade( sizebuf_t *msg ) S_FadeClientVolume( fadePercent, fadeOutSeconds, holdTime, fadeInSeconds ); } +/* +================== +CL_RequestMissingResources + +================== +*/ +qboolean CL_RequestMissingResources( void ) +{ + resource_t *p; + + if( !cls.dl.doneregistering && ( cls.dl.custom || cls.state == ca_validate )) + { + p = cl.resourcesneeded.pNext; + + if( p == &cl.resourcesneeded ) + { + cls.dl.doneregistering = true; + cls.dl.custom = false; + } + else if( !FBitSet( p->ucFlags, RES_WASMISSING )) + { + CL_MoveToOnHandList( cl.resourcesneeded.pNext ); + return true; + } + } + return false; +} + /* ================== CL_ParseCustomization @@ -732,18 +760,20 @@ CL_ParseServerData */ void CL_ParseServerData( sizebuf_t *msg ) { - int i, servercount, checksum; - int playernum, maxclients; char gamefolder[MAX_QPATH]; qboolean background; + int i; MsgDev( D_NOTE, "Serverdata packet received.\n" ); cls.timestart = Sys_DoubleTime(); cls.demowaiting = false; // server is changed - cls.state = ca_connected; clgame.load_sequence++; // now all hud sprites are invalid - cls.signon = 0; // reset signon state + + // wipe the client_t struct + if( !cls.changelevel && !cls.changedemo ) + CL_ClearState (); + cls.state = ca_connected; // Re-init hud video, especially if we changed game directories clgame.dllFuncs.pfnVidInit(); @@ -754,49 +784,22 @@ void CL_ParseServerData( sizebuf_t *msg ) if( cls.serverProtocol != PROTOCOL_VERSION ) Host_Error( "Server use invalid protocol (%i should be %i)\n", cls.serverProtocol, PROTOCOL_VERSION ); - servercount = MSG_ReadLong( msg ); - checksum = MSG_ReadLong( msg ); - playernum = MSG_ReadByte( msg ); - maxclients = MSG_ReadByte( msg ); + 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( 600, 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 ); background = MSG_ReadOneBit( msg ); - cls.changelevel = MSG_ReadOneBit( msg ); - Q_strncpy( gamefolder, MSG_ReadString( msg ), MAX_STRING ); + Q_strncpy( gamefolder, MSG_ReadString( msg ), MAX_QPATH ); host.features = (uint)MSG_ReadLong( msg ); if( clgame.maxModels > MAX_MODELS ) MsgDev( D_WARN, "server model limit is above client model limit %i > %i\n", clgame.maxModels, MAX_MODELS ); - if( cls.changelevel && cls.demoplayback ) - cls.changedemo = true; - - // wipe the client_t struct - CL_ClearState (); - - // allow console in multiplayer games - if( maxclients > 1 ) host.allow_console = true; - - // fill the client struct - cl.servercount = servercount; - cl.checksum = checksum; - cl.playernum = playernum; - cl.maxclients = maxclients; - - // set the background state - if( cls.demoplayback && ( cls.demonum != -1 )) - { - host.mouse_visible = false; - cl.background = true; - } - else cl.background = background; - - if( cls.changedemo ) - SCR_BeginLoadingPlaque( cl.background ); - if( Con_FixedFont( )) { // seperate the printfs so the server message can have a color @@ -812,8 +815,11 @@ void CL_ParseServerData( sizebuf_t *msg ) } // multiplayer game? - if( cl.maxclients != 1 ) + if( cl.maxclients > 1 ) { + // allow console in multiplayer games + host.allow_console = true; + // loading user settings CSCR_LoadDefaultCVars( "user.scr" ); @@ -822,6 +828,15 @@ void CL_ParseServerData( sizebuf_t *msg ) } else Cvar_Reset( "r_decals" ); + // set the background state + if( cls.demoplayback && ( cls.demonum != -1 )) + { + // re-init mouse + host.mouse_visible = false; + 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 ); @@ -841,7 +856,9 @@ void CL_ParseServerData( sizebuf_t *msg ) cl.viewentity = cl.playernum + 1; gameui.globals->maxClients = cl.maxclients; Q_strncpy( gameui.globals->maptitle, clgame.maptitle, sizeof( gameui.globals->maptitle )); - CL_InitEdicts (); // re-arrange edicts + + if( !cls.changelevel && !cls.changedemo ) + CL_InitEdicts (); // re-arrange edicts // get splash name if( cls.demoplayback && ( cls.demonum != -1 )) @@ -863,31 +880,6 @@ void CL_ParseServerData( sizebuf_t *msg ) #else MSG_WriteString( &cls.netchan.message, va( "sendres %i\n", cl.servercount )); #endif - if( scr_dark->value ) - { - screenfade_t *sf = &clgame.fade; - client_textmessage_t *title; - - title = CL_TextMessageGet( "GAMETITLE" ); - - if( title ) - { - // get settings from titles.txt - sf->fadeEnd = title->holdtime + title->fadeout; - sf->fadeReset = title->fadeout; - } - else sf->fadeEnd = sf->fadeReset = 5.0f; - - sf->fadeFlags = FFADE_IN; - sf->fader = sf->fadeg = sf->fadeb = 0; - sf->fadealpha = 255; - sf->fadeSpeed = (float)sf->fadealpha / sf->fadeReset; - sf->fadeReset += cl.time; - sf->fadeEnd += sf->fadeReset; - - Cvar_SetValue( "v_dark", 0.0f ); - } - // need to prep refresh at next oportunity cl.video_prepped = false; cl.audio_prepped = false; @@ -2276,10 +2268,37 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ) CL_ParseEvent( msg ); cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart; break; - case svc_version: - param1 = MSG_ReadLong( msg ); - if( param1 != PROTOCOL_VERSION ) - Host_Error( "Server is protocol %i instead of %i\n", param1, PROTOCOL_VERSION ); + case svc_changing: + if( MSG_ReadOneBit( msg )) + { + cls.changelevel = true; + S_StopAllSounds( true ); + + MsgDev( D_INFO, "Server changing, reconnecting\n" ); + + if( cls.demoplayback ) + { + SCR_BeginLoadingPlaque( cl.background ); + cls.changedemo = true; + } + } + else MsgDev( D_INFO, "Server disconnected, reconnecting\n" ); + + CL_ClearState (); + CL_InitEdicts (); // re-arrange edicts + + if( cls.demoplayback ) + { + cl.background = (cls.demonum != -1) ? true : false; + cls.state = ca_connected; + } + else + { + // g-cont. local client skip the challenge + if( SV_Active()) cls.state = ca_disconnected; + else cls.state = ca_connecting; + cls.connect_time = MAX_HEARTBEAT; + } break; case svc_setview: CL_ParseViewEntity( msg ); diff --git a/engine/client/cl_scrn.c b/engine/client/cl_scrn.c index 26a2d4bf..54baca0c 100644 --- a/engine/client/cl_scrn.c +++ b/engine/client/cl_scrn.c @@ -27,7 +27,7 @@ convar_t *cl_testlights; convar_t *cl_allow_levelshots; convar_t *cl_levelshot_name; convar_t *cl_envshot_size; -convar_t *scr_dark; +convar_t *v_dark; typedef struct { @@ -704,7 +704,7 @@ void SCR_Init( void ) scr_download = Cvar_Get( "scr_download", "0", 0, "downloading bar progress" ); cl_testlights = Cvar_Get( "cl_testlights", "0", 0, "test dynamic lights" ); cl_envshot_size = Cvar_Get( "cl_envshot_size", "256", FCVAR_ARCHIVE, "envshot size of cube side" ); - scr_dark = Cvar_Get( "v_dark", "0", 0, "starts level from dark screen" ); + v_dark = Cvar_Get( "v_dark", "0", 0, "starts level from dark screen" ); scr_viewsize = Cvar_Get( "viewsize", "120", FCVAR_ARCHIVE, "screen size" ); // register our commands diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 1d14a191..662525d6 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -2867,14 +2867,14 @@ int CL_DecalIndexFromName( const char *name ) { int i; - if( !name || !name[0] ) + if( !COM_CheckString( name )) return 0; // look through the loaded sprite name list for SpriteName - for( i = 0; i < (MAX_DECALS - 1) && host.draw_decals[i+1][0]; i++ ) + for( i = 1; i < MAX_DECALS && host.draw_decals[i][0]; i++ ) { - if( !Q_stricmp( name, host.draw_decals[i+1] )) - return i+1; + if( !Q_stricmp( name, host.draw_decals[i] )) + return i; } return 0; // invalid decal } diff --git a/engine/client/cl_video.c b/engine/client/cl_video.c index fe708953..f155e657 100644 --- a/engine/client/cl_video.c +++ b/engine/client/cl_video.c @@ -86,7 +86,7 @@ void SCR_CheckStartupVids( void ) char *afile, *pfile; string token; - if( Sys_CheckParm( "-nointro" ) || host.allow_console || cls.demonum != -1 ) + if( Sys_CheckParm( "-nointro" ) || host.allow_console || cls.demonum != -1 || GameState->nextstate != STATE_RUNFRAME ) { // don't run movies where we in developer-mode cls.movienum = -1; diff --git a/engine/client/cl_view.c b/engine/client/cl_view.c index 0689eccd..b928263a 100644 --- a/engine/client/cl_view.c +++ b/engine/client/cl_view.c @@ -353,7 +353,7 @@ void V_PostRender( void ) R_AllowFog( false ); R_Set2DMode( true ); - if( cls.state == ca_active && cls.scrshot_action != scrshot_mapshot ) + if( cls.state == ca_active && cls.signon == SIGNONS && cls.scrshot_action != scrshot_mapshot ) { SCR_TileClear(); CL_DrawHUD( CL_ACTIVE ); diff --git a/engine/client/client.h b/engine/client/client.h index 02b8c45c..9c6cf852 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -694,7 +694,7 @@ extern convar_t *scr_centertime; extern convar_t *scr_viewsize; extern convar_t *scr_download; extern convar_t *scr_loading; -extern convar_t *scr_dark; // start from dark +extern convar_t *v_dark; // start from dark extern convar_t *net_graph; extern convar_t *rate; @@ -837,6 +837,7 @@ _inline cl_entity_t *CL_EDICT_NUM( int n ) void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ); void CL_ParseTempEntity( sizebuf_t *msg ); qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf ); +qboolean CL_RequestMissingResources( void ); // // cl_scrn.c @@ -911,6 +912,7 @@ qboolean CL_GetEntitySpatialization( struct channel_s *ch ); qboolean CL_GetMovieSpatialization( struct rawchan_s *ch ); void CL_ComputePlayerOrigin( cl_entity_t *clent ); void CL_UpdateEntityFields( cl_entity_t *ent ); +void CL_MoveThirdpersonCamera( void ); qboolean CL_IsPlayerIndex( int idx ); void CL_SetIdealPitch( void ); void CL_EmitEntities( void ); diff --git a/engine/client/gl_image.c b/engine/client/gl_image.c index 52bc3bf4..917573d4 100644 --- a/engine/client/gl_image.c +++ b/engine/client/gl_image.c @@ -1144,7 +1144,8 @@ static qboolean GL_UploadTexture( gltexture_t *tex, rgbdata_t *pic ) normalMap = FBitSet( tex->flags, TF_NORMALMAP ) ? true : false; numSides = FBitSet( pic->flags, IMAGE_CUBEMAP ) ? 6 : 1; - // uploading texture into video memory + // uploading texture into video memory, change the binding + glState.currentTextures[glState.activeTMU] = tex->texnum; pglBindTexture( tex->target, tex->texnum ); for( i = 0; i < numSides; i++ ) diff --git a/engine/client/gl_refrag.c b/engine/client/gl_refrag.c index b68b1631..f300580a 100644 --- a/engine/client/gl_refrag.c +++ b/engine/client/gl_refrag.c @@ -151,29 +151,10 @@ void R_AddEfrags( cl_entity_t *ent ) lastlink = &ent->efrag; r_pefragtopnode = NULL; - // NOTE: can't copy these bounds directly into model->mins\model->maxs - // because all other code don't expected this - if( ent->model->type == mod_studio ) + for( i = 0; i < 3; i++ ) { - studiohdr_t *phdr = (studiohdr_t *)Mod_StudioExtradata( ent->model ); - mstudioseqdesc_t *pseqdesc; - - if( !phdr ) return; - pseqdesc = (mstudioseqdesc_t *)((byte *)phdr + phdr->seqindex); - - for( i = 0; i < 3; i++ ) - { - r_emins[i] = ent->origin[i] + pseqdesc[0].bbmin[i]; - r_emaxs[i] = ent->origin[i] + pseqdesc[0].bbmax[i]; - } - } - else - { - for( i = 0; i < 3; i++ ) - { - r_emins[i] = ent->origin[i] + ent->model->mins[i]; - r_emaxs[i] = ent->origin[i] + ent->model->maxs[i]; - } + r_emins[i] = ent->origin[i] + ent->model->mins[i]; + r_emaxs[i] = ent->origin[i] + ent->model->maxs[i]; } R_SplitEntityOnNode( cl.worldmodel->nodes ); diff --git a/engine/client/gl_rmisc.c b/engine/client/gl_rmisc.c index 0060505d..0fd75266 100644 --- a/engine/client/gl_rmisc.c +++ b/engine/client/gl_rmisc.c @@ -17,6 +17,7 @@ GNU General Public License for more details. #include "client.h" #include "gl_local.h" #include "mod_local.h" +#include "shake.h" typedef struct { @@ -461,6 +462,31 @@ void R_NewMap( void ) R_ParseDetailTextures( filepath ); } + if( v_dark->value ) + { + screenfade_t *sf = &clgame.fade; + client_textmessage_t *title; + + title = CL_TextMessageGet( "GAMETITLE" ); + + if( title ) + { + // get settings from titles.txt + sf->fadeEnd = title->holdtime + title->fadeout; + sf->fadeReset = title->fadeout; + } + else sf->fadeEnd = sf->fadeReset = 5.0f; + + sf->fadeFlags = FFADE_IN; + sf->fader = sf->fadeg = sf->fadeb = 0; + sf->fadealpha = 255; + sf->fadeSpeed = (float)sf->fadealpha / sf->fadeReset; + sf->fadeReset += cl.time; + sf->fadeEnd += sf->fadeReset; + + Cvar_SetValue( "v_dark", 0.0f ); + } + // clear out efrags in case the level hasn't been reloaded for( i = 0; i < cl.worldmodel->numleafs; i++ ) cl.worldmodel->leafs[i+1].efrags = NULL; diff --git a/engine/common/console.c b/engine/common/console.c index 48526937..d4a56bcd 100644 --- a/engine/common/console.c +++ b/engine/common/console.c @@ -2130,11 +2130,7 @@ void Con_DrawConsole( void ) case ca_connected: case ca_validate: // force to show console always for -dev 3 and higher - if( con.vislines ) - { - GL_CleanupAllTextureUnits(); // ugly hack to remove blinking voiceicon.spr during loading - Con_DrawSolidConsole( con.vislines ); - } + Con_DrawSolidConsole( con.vislines ); break; case ca_active: case ca_cinematic: diff --git a/engine/common/host.c b/engine/common/host.c index 56c2edbc..37ff7e2c 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -912,7 +912,7 @@ int EXPORT Host_Main( const char *progname, int bChangeGame, pfnChangeGame func Cmd_AddCommand ( "sys_error", Sys_Error_f, "just throw a fatal error to test shutdown procedures"); Cmd_AddCommand ( "host_error", Host_Error_f, "just throw a host error to test shutdown procedures"); Cmd_AddCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons"); - } + } host_maxfps = Cvar_Get( "fps_max", "72", FCVAR_ARCHIVE, "host fps upper limit" ); host_framerate = Cvar_Get( "host_framerate", "0", 0, "locks frame timing to this value in seconds" ); diff --git a/engine/common/host_state.c b/engine/common/host_state.c index 65868a2f..8894a04e 100644 --- a/engine/common/host_state.c +++ b/engine/common/host_state.c @@ -43,6 +43,7 @@ void COM_NewGame( char const *pMapName ) GameState->backgroundMap = false; GameState->landmarkName[0] = 0; + GameState->loadGame = false; GameState->newGame = true; } @@ -56,6 +57,7 @@ void COM_LoadLevel( char const *pMapName, qboolean background ) GameState->backgroundMap = background; GameState->landmarkName[0] = 0; + GameState->loadGame = false; GameState->newGame = false; } diff --git a/engine/common/mod_bmodel.c b/engine/common/mod_bmodel.c index d7a88207..49a2a96c 100644 --- a/engine/common/mod_bmodel.c +++ b/engine/common/mod_bmodel.c @@ -134,6 +134,7 @@ typedef struct int lightmap_samples; // samples per lightmap (1 or 3) int version; // model version qboolean isworld; + qboolean vis_errors; // don't spam about vis } dbspmodel_t; typedef struct @@ -447,7 +448,7 @@ void Mod_PrintWorldStats_f( void ) Mod_DecompressVis =================== */ -static void Mod_DecompressVis( const byte *in, const byte *inend, byte *out, byte *outend ) +static void Mod_DecompressVis( dbspmodel_t *bmod, const byte *in, const byte *inend, byte *out, byte *outend ) { byte *outstart = out; int c; @@ -456,8 +457,12 @@ static void Mod_DecompressVis( const byte *in, const byte *inend, byte *out, byt { if( in == inend ) { - MsgDev( D_WARN, "Mod_DecompressVis: input underrun (decompressed %i of %i output bytes)\n", - (int)(out - outstart), (int)(outend - outstart)); + if( !bmod->vis_errors ) + { + MsgDev( D_WARN, "Mod_DecompressVis: input underrun (decompressed %i of %i output bytes)\n", + (int)(out - outstart), (int)(outend - outstart)); + bmod->vis_errors = true; + } return; } @@ -471,8 +476,12 @@ static void Mod_DecompressVis( const byte *in, const byte *inend, byte *out, byt { if( in == inend ) { - MsgDev( D_NOTE, "Mod_DecompressVis: input underrun (during zero-run) (decompressed %i of %i output bytes)\n", - (int)(out - outstart), (int)(outend - outstart)); + if( !bmod->vis_errors ) + { + MsgDev( D_NOTE, "Mod_DecompressVis: input underrun (during zero-run) (decompressed %i of %i output bytes)\n", + (int)(out - outstart), (int)(outend - outstart)); + bmod->vis_errors = true; + } return; } @@ -480,8 +489,12 @@ static void Mod_DecompressVis( const byte *in, const byte *inend, byte *out, byt { if( out == outend ) { - MsgDev( D_NOTE, "Mod_DecompressVis: output overrun (decompressed %i of %i output bytes)\n", - (int)(out - outstart), (int)(outend - outstart)); + if( !bmod->vis_errors ) + { + MsgDev( D_NOTE, "Mod_DecompressVis: output overrun (decompressed %i of %i output bytes)\n", + (int)(out - outstart), (int)(outend - outstart)); + bmod->vis_errors = true; + } return; } *out++ = 0; @@ -2369,7 +2382,7 @@ static void Mod_LoadLeafs( dbspmodel_t *bmod ) byte *outrow = world.visdata + out->cluster * world.visbytes; byte *outrowend = world.visdata + (out->cluster + 1) * world.visbytes; - Mod_DecompressVis( inrow, inrowend, outrow, outrowend ); + Mod_DecompressVis( bmod, inrow, inrowend, outrow, outrowend ); } else MsgDev( D_WARN, "Mod_LoadLeafs: invalid visofs for leaf #%i\n", i ); } @@ -2621,12 +2634,12 @@ qboolean Mod_LoadBmodelLumps( const byte *mod_base, qboolean isworld ) for( i = 0; i < ARRAYSIZE( extlumps ); i++ ) Mod_LoadLump( mod_base, &extlumps[i], &worldstats[ARRAYSIZE( srclumps ) + i], isworld ? (LUMP_SAVESTATS|LUMP_SILENT) : 0 ); - if( loadstat.numerrors ) + if( !bmod->isworld && loadstat.numerrors ) { Con_DPrintf( "Mod_Load%s: %i error(s), %i warning(s)\n", isworld ? "World" : "Brush", loadstat.numerrors, loadstat.numwarnings ); return false; // there were errors, we can't load this map } - else if( loadstat.numwarnings ) + else if( !bmod->isworld && loadstat.numwarnings ) Con_DPrintf( "Mod_Load%s: %i warning(s)\n", isworld ? "World" : "Brush", loadstat.numwarnings ); // load into heap diff --git a/engine/common/mod_local.h b/engine/common/mod_local.h index 34f5b015..41d7fa9d 100644 --- a/engine/common/mod_local.h +++ b/engine/common/mod_local.h @@ -65,7 +65,6 @@ GNU General Public License for more details. #define MODEL_WORLD BIT( 29 ) // it's a worldmodel #define MODEL_CLIENT BIT( 30 ) // client sprite - // goes into world.flags #define FWORLD_SKYSPHERE BIT( 0 ) #define FWORLD_CUSTOM_SKYBOX BIT( 1 ) diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 15e5ac0e..ca30c10a 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -23,7 +23,7 @@ GNU General Public License for more details. #define svc_nop 1 // does nothing #define svc_disconnect 2 // kick client from server #define svc_event 3 // playback event queue -#define svc_version 4 // [long] server version +#define svc_changing 4 // changelevel by server request #define svc_setview 5 // [short] entity number #define svc_sound 6 // #define svc_time 7 // [float] server time diff --git a/engine/common/zone.c b/engine/common/zone.c index 2cdc3cd9..08e79309 100644 --- a/engine/common/zone.c +++ b/engine/common/zone.c @@ -453,11 +453,15 @@ void Mem_PrintList( size_t minallocationsize ) Con_Printf( "memory pool list:\n"" ^3size name\n"); for( pool = poolchain; pool; pool = pool->next ) { + long changed_size = (long)pool->totalsize - (long)pool->lastchecksize; + // poolnames can contain color symbols, make sure what color is reset - if( ((long)pool->totalsize - pool->lastchecksize ) != 0 ) + if( changed_size != 0 ) { - Con_Printf( "%10s (%10s actual) %s (^7+%s change)\n", Q_memprint( pool->totalsize ), Q_memprint( pool->realsize ), - pool->name, Q_memprint( pool->totalsize - pool->lastchecksize )); + char sign = (changed_size < 0) ? '-' : '+'; + + Con_Printf( "%10s (%10s actual) %s (^7%c%s change)\n", Q_memprint( pool->totalsize ), Q_memprint( pool->realsize ), + pool->name, sign, Q_memprint( abs( changed_size ))); } else { diff --git a/engine/server/server.h b/engine/server/server.h index 5a4419e7..d1bae3d9 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -432,8 +432,6 @@ extern convar_t sv_skyname; extern convar_t sv_skyspeed; extern convar_t sv_skyangle; extern convar_t sv_consistency; -extern convar_t sv_spawntime; -extern convar_t sv_changetime; extern convar_t sv_password; extern convar_t sv_uploadmax; extern convar_t deathmatch; @@ -473,6 +471,8 @@ void SV_ProcessFile( sv_client_t *cl, char *filename ); void SV_SendResourceList( sv_client_t *cl ); void SV_AddToMaster( netadr_t from, sizebuf_t *msg ); qboolean SV_IsSimulating( void ); +qboolean SV_InitGame( void ); +void SV_FreeClients( void ); void Master_Add( void ); void Master_Heartbeat( void ); void Master_Packet( void ); @@ -564,6 +564,7 @@ int SV_EstimateNeededResources( sv_client_t *cl ); void SV_ClearResourceList( resource_t *pList ); void SV_BatchUploadRequest( sv_client_t *cl ); void SV_SendResources( sv_client_t *cl, sizebuf_t *msg ); +void SV_ClearResourceLists( sv_client_t *cl ); int SV_TransferConsistencyInfo( void ); // diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index 9e47ac12..00e55ee6 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -204,6 +204,33 @@ int SV_CheckIPRestrictions( netadr_t from ) return 1; } +/* +================ +SV_FindEmptySlot + +Get slot # and set client_t pointer for player, if possible +We don't do this search on a "reconnect, we just reuse the slot +================ +*/ +int SV_FindEmptySlot( netadr_t from, int *pslot, sv_client_t **ppClient ) +{ + sv_client_t *cl; + int i; + + for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ ) + { + if( cl->state == cs_free ) + { + *ppClient = cl; + *pslot = i; + return 1; + } + } + + SV_RejectConnection( from, "server is full\n" ); + return 0; +} + /* ================== SV_ConnectClient @@ -217,6 +244,8 @@ void SV_ConnectClient( netadr_t from ) char physinfo[MAX_PHYSINFO_STRING]; char protinfo[MAX_INFO_STRING]; sv_client_t temp, *cl, *newcl; + qboolean reconnect = false; + int nClientSlot = 0; int qport, version; int i, edictnum; int count = 0; @@ -281,23 +310,6 @@ void SV_ConnectClient( netadr_t from ) Q_strncpy( userinfo, s, sizeof( userinfo )); - // quick reject - for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ ) - { - if( cl->state == cs_free || cl->state == cs_zombie ) - continue; - - if( NET_CompareBaseAdr( from, cl->netchan.remote_address ) && ( cl->netchan.qport == qport || from.port == cl->netchan.remote_address.port )) - { - if( !NET_IsLocalAddress( from ) && ( host.realtime - cl->connection_started ) < sv_reconnect_limit->value ) - { - SV_RejectConnection( from, "too soon\n" ); - return; - } - break; - } - } - // check connection password (don't verify local client) if( !NET_IsLocalAddress( from ) && sv_password.string[0] && Q_stricmp( sv_password.string, Info_ValueForKey( userinfo, "password" ))) { @@ -319,39 +331,35 @@ void SV_ConnectClient( netadr_t from ) if( NET_CompareBaseAdr( from, cl->netchan.remote_address ) && ( cl->netchan.qport == qport || from.port == cl->netchan.remote_address.port )) { - MsgDev( D_INFO, "%s:reconnect\n", NET_AdrToString( from )); - newcl = cl; - goto gotnewcl; - } - } - - // find a client slot - newcl = NULL; - - for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ ) - { - if( cl->state == cs_free ) - { + reconnect = true; newcl = cl; break; } } - if( !newcl ) + // A reconnecting client will re-use the slot found above when checking for reconnection. + // the slot will be wiped clean. + if( !reconnect ) { - SV_RejectConnection( from, "server is full\n" ); - return; + // cConnect the client if there are empty slots. + if( !SV_FindEmptySlot( from, &nClientSlot, &newcl )) + return; } + else + { + MsgDev( D_INFO, "%s:reconnect\n", NET_AdrToString( from )); + } + + // find a client slot + ASSERT( newcl != NULL ); // build a new connection // accept the new client -gotnewcl: // this is the only place a sv_client_t is ever initialized - if( svs.maxclients == 1 ) // save physinfo for singleplayer Q_strncpy( physinfo, newcl->physinfo, sizeof( physinfo )); - *newcl = temp; + *newcl = temp; // FIXME: don't clearing all the fields if( svs.maxclients == 1 ) // restore physinfo for singleplayer Q_strncpy( newcl->physinfo, physinfo, sizeof( physinfo )); @@ -396,6 +404,7 @@ gotnewcl: // parse some info from the info strings (this can override cl_updaterate) Q_strncpy( newcl->userinfo, userinfo, sizeof( newcl->userinfo )); SV_UserinfoChanged( newcl, newcl->userinfo ); + SV_ClearResourceLists( newcl ); newcl->next_messagetime = host.realtime + newcl->cl_updaterate; newcl->next_sendinfotime = 0.0; @@ -1410,7 +1419,6 @@ void SV_SendServerdata( sizebuf_t *msg, sv_client_t *cl ) MSG_WriteString( msg, sv.name ); MSG_WriteString( msg, STRING( svgame.edicts->v.message )); // Map Message MSG_WriteOneBit( msg, sv.background ); // tell client about background map - MSG_WriteOneBit( msg, svgame.globals->changelevel ); MSG_WriteString( msg, GI->gamefolder ); MSG_WriteLong( msg, host.features ); @@ -2489,6 +2497,8 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg ) client_frame_t *frame; char *s; + ASSERT( cl->frames != NULL ); + // calc ping time frame = &cl->frames[cl->netchan.incoming_acknowledged & SV_UPDATE_MASK]; diff --git a/engine/server/sv_custom.c b/engine/server/sv_custom.c index 979899bb..d17b4e30 100644 --- a/engine/server/sv_custom.c +++ b/engine/server/sv_custom.c @@ -357,6 +357,12 @@ void SV_ClearResourceList( resource_t *pList ) pList->pNext = pList; } +void SV_ClearResourceLists( sv_client_t *cl ) +{ + SV_ClearResourceList( &cl->resourcesneeded ); + SV_ClearResourceList( &cl->resourcesonhand ); +} + int SV_EstimateNeededResources( sv_client_t *cl ) { int missing = 0; diff --git a/engine/server/sv_frame.c b/engine/server/sv_frame.c index 9042dc33..f542d16e 100644 --- a/engine/server/sv_frame.c +++ b/engine/server/sv_frame.c @@ -629,7 +629,7 @@ void SV_WriteEntitiesToClient( sv_client_t *cl, sizebuf_t *msg ) svs.next_client_entities = 0; // delta is broken for now, cannot keep connected clients - SV_FinalMessage( "Server will restart due delta is outdated", true ); + SV_FinalMessage( "Server will restart due delta is outdated\n", true ); } // copy the entity states out diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index ebb0c149..134eb916 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -4948,7 +4948,7 @@ qboolean SV_LoadProgs( const char *name ) svgame.stringspool = Mem_AllocPool( "Server Strings" ); // fire once - MsgDev( D_INFO, "Dll loaded for mod %s\n", svgame.dllFuncs.pfnGetGameDescription( )); + Con_Printf( "Dll loaded for game ^2\"%s\"\n", svgame.dllFuncs.pfnGetGameDescription( )); // all done, initialize game svgame.dllFuncs.pfnGameInit(); diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 6d40c91b..a070b364 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -478,17 +478,15 @@ void SV_ActivateServer( int runPhysics ) // parse user-specified resources SV_CreateGenericResources(); - sv.state = ss_active; - if( runPhysics ) { - sv.frametime = bound( 0.1, sv_spawntime.value, 0.8 ); numFrames = (svs.maxclients <= 1) ? 2 : 8; + sv.frametime = 0.1; } else { - sv.frametime = bound( 0.001, sv_changetime.value, 0.1 ); - numFrames = 0; + sv.frametime = (svgame.globals->changelevel) ? 0.1 : 0.001; + numFrames = 1; } // run some frames to allow everything to settle @@ -512,14 +510,6 @@ void SV_ActivateServer( int runPhysics ) Netchan_Clear( &cl->netchan ); cl->delta_sequence = -1; - - if( svs.maxclients <= 1 ) - SV_SendServerdata( &msg, cl ); - else SV_BuildReconnect( &cl->netchan.message ); - - Netchan_CreateFragments( &cl->netchan, &msg ); - Netchan_FragSend( &cl->netchan ); - MSG_Clear( &msg ); } // invoke to refresh all movevars @@ -543,6 +533,7 @@ void SV_ActivateServer( int runPhysics ) Mod_FreeUnused (); host.movevars_changed = true; + sv.state = ss_active; Con_DPrintf( "level loaded at %.2f sec\n", Sys_DoubleTime() - svs.timestart ); @@ -574,6 +565,7 @@ void SV_DeactivateServer( void ) svgame.globals->time = sv.time; svgame.dllFuncs.pfnServerDeactivate(); + sv.state = ss_dead; SV_FreeEdicts (); @@ -594,7 +586,6 @@ void SV_DeactivateServer( void ) svgame.numEntities = svs.maxclients + 1; // clients + world svgame.globals->startspot = 0; svgame.globals->mapname = 0; - sv.state = ss_dead; } /* @@ -634,6 +625,7 @@ void SV_ShutdownGame( void ) if( !GameState->loadGame ) SV_ClearGameState(); + SV_FinalMessage( "", true ); S_StopBackgroundTrack(); if( GameState->newGame ) @@ -647,24 +639,6 @@ void SV_ShutdownGame( void ) } } -/* -================ -SV_AllocClientFrames - -allocate delta-compression frames for each client -================ -*/ -void SV_AllocClientFrames( void ) -{ - sv_client_t *cl; - int i; - - for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ ) - { - cl->frames = Z_Realloc( cl->frames, SV_UPDATE_BACKUP * sizeof( client_frame_t )); - } -} - /* ================ SV_SetupClients @@ -680,11 +654,13 @@ void SV_SetupClients( void ) if( svs.maxclients != (int)sv_maxclients->value ) changed_maxclients = true; - svs.maxclients = sv_maxclients->value; // copy the actual value from cvar if( !changed_maxclients ) return; // nothing to change // if clients count was changed we need to run full shutdown procedure -// Host_ShutdownServer(); + if( svs.maxclients ) Host_ShutdownServer(); + + // copy the actual value from cvar + svs.maxclients = (int)sv_maxclients->value; // dedicated servers are can't be single player and are usually DM if( host.type == HOST_DEDICATED ) @@ -727,7 +703,6 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba edict_t *ent; SV_SetupClients(); - SV_AllocClientFrames(); if( !SV_InitGame( )) return false; diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 5b3875d7..96475a7b 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -98,9 +98,6 @@ CVAR_DEFINE_AUTO( sv_skydir_z, "1", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "sky rotation CVAR_DEFINE_AUTO( sv_skyangle, "0", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "skybox rotational angle (in degrees)" ); CVAR_DEFINE_AUTO( sv_skyspeed, "0", 0, "skybox rotational speed" ); -CVAR_DEFINE( sv_spawntime, "host_spawntime", "0.1", FCVAR_ARCHIVE, "host.frametime on spawn new map (force to 0.8 if have problems)" ); -CVAR_DEFINE( sv_changetime, "host_changetime", "0.001", FCVAR_ARCHIVE, "host.frametime on changelevel (force to 0.1 if have player stucks)" ); - // obsolete cvars which we should keep because game DLL's will be relies on it CVAR_DEFINE_AUTO( showtriggers, "0", FCVAR_LATCH, "debug cvar shows triggers" ); CVAR_DEFINE_AUTO( sv_airmove, "1", FCVAR_SERVER, "obsolete, compatibility issues" ); @@ -320,10 +317,7 @@ void SV_ReadPackets( void ) continue; if( cl->netchan.remote_address.port != net_from.port ) - { - MsgDev( D_NOTE, "SV_ReadPackets: fixing up a translated port\n"); cl->netchan.remote_address.port = net_from.port; - } if( Netchan_Process( &cl->netchan, &net_message )) { @@ -331,7 +325,7 @@ void SV_ReadPackets( void ) SetBits( cl->flags, FCL_SEND_NET_MESSAGE ); // reply at end of frame // this is a valid, sequenced packet, so process it - if( cl->state != cs_zombie ) + if( cl->frames != NULL && cl->state != cs_zombie ) { SV_ExecuteClientMessage( cl, &net_message ); svgame.globals->frametime = sv.frametime; @@ -350,7 +344,7 @@ void SV_ReadPackets( void ) SetBits( cl->flags, FCL_SEND_NET_MESSAGE ); // reply at end of frame // this is a valid, sequenced packet, so process it - if( cl->state != cs_zombie ) + if( cl->frames != NULL && cl->state != cs_zombie ) { SV_ExecuteClientMessage( cl, &net_message ); svgame.globals->frametime = sv.frametime; @@ -785,10 +779,6 @@ void SV_Init( void ) sv_hostmap = Cvar_Get( "hostmap", GI->startmap, 0, "keep name of last entered map" ); Cvar_RegisterVariable (&sv_password); Cvar_RegisterVariable (&sv_lan); - - Cvar_RegisterVariable (&sv_spawntime); - Cvar_RegisterVariable (&sv_changetime); - Cvar_RegisterVariable (&violence_ablood); Cvar_RegisterVariable (&violence_hblood); Cvar_RegisterVariable (&violence_agibs); @@ -824,11 +814,25 @@ void SV_FinalMessage( const char *message, qboolean reconnect ) int i; MSG_Init( &msg, "FinalMessage", msg_buf, sizeof( msg_buf )); - MSG_BeginServerCmd( &msg, svc_print ); - MSG_WriteString( &msg, va( "%s\n", message )); - if( reconnect ) SV_BuildReconnect( &msg ); - else MSG_BeginServerCmd( &msg, svc_disconnect ); + if( COM_CheckString( message )) + { + MSG_BeginServerCmd( &msg, svc_print ); + MSG_WriteString( &msg, message ); + } + + if( reconnect ) + { + MSG_BeginServerCmd( &msg, svc_changing ); + + if( GameState->loadGame || svs.maxclients > 1 ) + MSG_WriteOneBit( &msg, 1 ); // changelevel + else MSG_WriteOneBit( &msg, 0 ); + } + else + { + MSG_BeginServerCmd( &msg, svc_disconnect ); + } // send it twice // stagger the packets to crutch operating system limited buffers @@ -841,6 +845,13 @@ void SV_FinalMessage( const char *message, qboolean reconnect ) Netchan_Transmit( &cl->netchan, MSG_GetNumBytesWritten( &msg ), MSG_GetData( &msg )); } +/* +================ +SV_FreeClients + +release server clients +================ +*/ void SV_FreeClients( void ) { if( svs.maxclients != 0 ) @@ -859,8 +870,6 @@ void SV_FreeClients( void ) svs.num_client_entities = 0; svs.next_client_entities = 0; } - - svs.maxclients = 0; } } @@ -888,11 +897,13 @@ void SV_Shutdown( const char *finalmsg ) NET_Config( false ); SV_UnloadProgs (); + CL_Drop(); // free current level memset( &sv, 0, sizeof( sv )); SV_FreeClients(); + svs.maxclients = 0; Log_Printf( "Server shutdown\n" ); Log_Close(); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index c1b25c93..5b19fb0e 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -886,7 +886,7 @@ static edict_t *SV_PushMove( edict_t *pusher, float movetime ) sv_pushed_t *p, *pushed_p; edict_t *check; - if( VectorIsNull( pusher->v.velocity )) + if( svgame.globals->changelevel || VectorIsNull( pusher->v.velocity )) { pusher->v.ltime += movetime; return NULL; @@ -1004,7 +1004,7 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime ) vec3_t org, org2, temp; edict_t *check; - if( VectorIsNull( pusher->v.avelocity )) + if( svgame.globals->changelevel || VectorIsNull( pusher->v.avelocity )) { pusher->v.ltime += movetime; return NULL; diff --git a/engine/server/sv_save.c b/engine/server/sv_save.c index 0eb8147f..ef940962 100644 --- a/engine/server/sv_save.c +++ b/engine/server/sv_save.c @@ -871,7 +871,7 @@ SAVERESTOREDATA *SV_LoadSaveData( const char *level ) int i, id, size, version; Q_snprintf( name, sizeof( name ), "save/%s.HL1", level ); - Con_Printf( "Loading game from %s...\n", name ); + Con_DPrintf( "Loading game from %s...\n", name ); pFile = FS_Open( name, "rb", true ); if( !pFile ) @@ -1957,6 +1957,7 @@ void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char } SV_InactivateClients (); + SV_FinalMessage( "", true ); SV_DeactivateServer (); if( !SV_SpawnServer( level, startspot, false )) @@ -2142,8 +2143,8 @@ qboolean SV_LoadGame( const char *pPath ) if( !FS_FileExists( pPath, true )) return false; - SV_InitGameProgs(); - if( !svgame.hInstance ) + // initialize game if needs + if( !SV_InitGame( )) return false; pFile = FS_Open( pPath, "rb", true ); diff --git a/mainui/extdll.h b/mainui/extdll.h index 1a86543d..03dc68c2 100644 --- a/mainui/extdll.h +++ b/mainui/extdll.h @@ -33,6 +33,9 @@ GNU General Public License for more details. #include #define bound( min, num, max ) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min)) +#define SetBits( iBitVector, bits ) ((iBitVector) = (iBitVector) | (bits)) +#define ClearBits( iBitVector, bits ) ((iBitVector) = (iBitVector) & ~(bits)) +#define FBitSet( iBitVector, bit ) ((iBitVector) & (bit)) typedef int (*cmpfunc)( const void *a, const void *b ); diff --git a/mainui/menu_playersetup.cpp b/mainui/menu_playersetup.cpp index 96dc0c74..feecf7ef 100644 --- a/mainui/menu_playersetup.cpp +++ b/mainui/menu_playersetup.cpp @@ -336,15 +336,10 @@ UI_PlayerSetup_Init */ static void UI_PlayerSetup_Init( void ) { - bool game_hlRally = FALSE; int addFlags = 0; memset( &uiPlayerSetup, 0, sizeof( uiPlayerSetup_t )); - // disable playermodel preview for HLRally to prevent crash - if( !stricmp( gMenu.m_gameinfo.gamefolder, "hlrally" )) - game_hlRally = TRUE; - if( gMenu.m_gameinfo.flags & GFL_NOMODELS ) addFlags |= QMF_INACTIVE; @@ -413,10 +408,10 @@ static void UI_PlayerSetup_Init( void ) uiPlayerSetup.model.generic.id = ID_MODEL; uiPlayerSetup.model.generic.type = QMTYPE_SPINCONTROL; uiPlayerSetup.model.generic.flags = QMF_CENTER_JUSTIFY|QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|addFlags; - uiPlayerSetup.model.generic.x = game_hlRally ? 320 : 702; - uiPlayerSetup.model.generic.y = game_hlRally ? 320 : 590; - uiPlayerSetup.model.generic.width = game_hlRally ? 256 : 176; - uiPlayerSetup.model.generic.height = game_hlRally ? 36 : 32; + uiPlayerSetup.model.generic.x = FBitSet( gMenu.m_gameinfo.flags, GFL_NOMODELS ) ? 320 : 702; + uiPlayerSetup.model.generic.y = FBitSet( gMenu.m_gameinfo.flags, GFL_NOMODELS ) ? 320 : 590; + uiPlayerSetup.model.generic.width = FBitSet( gMenu.m_gameinfo.flags, GFL_NOMODELS ) ? 256 : 176; + uiPlayerSetup.model.generic.height = FBitSet( gMenu.m_gameinfo.flags, GFL_NOMODELS ) ? 36 : 32; uiPlayerSetup.model.generic.callback = UI_PlayerSetup_Callback; uiPlayerSetup.model.generic.statusText = "Select a model for representation in multiplayer"; uiPlayerSetup.model.minValue = 0; @@ -474,11 +469,11 @@ static void UI_PlayerSetup_Init( void ) UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.done ); UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.AdvOptions ); // disable playermodel preview for HLRally to prevent crash - if( game_hlRally == FALSE ) + if( !FBitSet( gMenu.m_gameinfo.flags, GFL_NOMODELS )) UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.view ); UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.name ); - if( !( gMenu.m_gameinfo.flags & GFL_NOMODELS )) + if( !FBitSet( gMenu.m_gameinfo.flags, GFL_NOMODELS )) { UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.model ); UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.topColor ); diff --git a/xash.dsw b/xash.dsw index 05979804..88cfb178 100644 --- a/xash.dsw +++ b/xash.dsw @@ -51,18 +51,6 @@ Package=<4> ############################################################################### -Project: "mainui2"=.\mainui2\mainui2.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - Project: "vgui"=.\utils\vgui\lib\vgui.dsp - Package Owner=<4> Package=<5>