28 Feb 2018
This commit is contained in:
parent
64609ae475
commit
6441d5bfa2
|
@ -248,7 +248,7 @@ typedef struct render_interface_s
|
|||
// handle decals which hit mod_studio or mod_sprite
|
||||
void (*R_StudioDecalShoot)( int decalTexture, struct cl_entity_s *ent, const float *start, const float *pos, int flags, modelstate_t *state );
|
||||
// prepare studio decals for save
|
||||
int (*R_CreateStudioDecalList)( decallist_t *pList, int count, qboolean changelevel );
|
||||
int (*R_CreateStudioDecalList)( decallist_t *pList, int count );
|
||||
// clear decals by engine request (e.g. for demo recording or vid_restart)
|
||||
void (*R_ClearStudioDecals)( void );
|
||||
// grab r_speeds message
|
||||
|
|
|
@ -839,7 +839,7 @@ int pfnCheckGameDll( void )
|
|||
{
|
||||
void *hInst;
|
||||
|
||||
if( SV_Active( )) return true;
|
||||
if( SV_Initialized( )) return true;
|
||||
|
||||
if(( hInst = Com_LoadLibrary( GI->game_dll, true )) != NULL )
|
||||
{
|
||||
|
|
|
@ -2353,7 +2353,6 @@ void CL_InitLocal( void )
|
|||
bottomcolor = Cvar_Get( "bottomcolor", "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "player bottom color" );
|
||||
cl_lw = Cvar_Get( "cl_lw", "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" );
|
||||
Cvar_Get( "cl_lc", "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable lag compensation" );
|
||||
Cvar_Get( "msg", "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "message filter for server notifications" );
|
||||
Cvar_Get( "password", "", FCVAR_USERINFO, "server password" );
|
||||
Cvar_Get( "team", "", FCVAR_USERINFO, "player team" );
|
||||
Cvar_Get( "skin", "", FCVAR_USERINFO, "player skin" );
|
||||
|
@ -2388,6 +2387,7 @@ void CL_InitLocal( void )
|
|||
Cmd_AddCommand ("drop", NULL, "drop current/specified item or weapon" );
|
||||
Cmd_AddCommand ("gametitle", NULL, "show game logo" );
|
||||
Cmd_AddCommand ("god", NULL, "enable godmode" );
|
||||
Cmd_AddCommand ("fly", NULL, "enable fly mode" );
|
||||
Cmd_AddCommand ("fov", NULL, "set client field of view" );
|
||||
Cmd_AddCommand ("log", NULL, "logging server events" );
|
||||
|
||||
|
|
|
@ -737,46 +737,67 @@ CL_ParseServerData
|
|||
*/
|
||||
void CL_ParseServerData( sizebuf_t *msg )
|
||||
{
|
||||
string gamefolder;
|
||||
int i, servercount, checksum;
|
||||
int playernum, maxclients;
|
||||
char gamefolder[MAX_QPATH];
|
||||
qboolean background;
|
||||
int i;
|
||||
|
||||
MsgDev( D_NOTE, "Serverdata packet received.\n" );
|
||||
|
||||
cls.demowaiting = false; // server is changed
|
||||
clgame.load_sequence++; // now all hud sprites are invalid
|
||||
|
||||
// wipe the client_t struct
|
||||
if( !cls.changelevel && !cls.changedemo )
|
||||
CL_ClearState ();
|
||||
cls.state = ca_connected;
|
||||
clgame.load_sequence++; // now all hud sprites are invalid
|
||||
cls.signon = 0; // reset signon state
|
||||
|
||||
// Re-init hud video, especially if we changed game directories
|
||||
clgame.dllFuncs.pfnVidInit();
|
||||
|
||||
// parse protocol version number
|
||||
i = MSG_ReadLong( msg );
|
||||
cls.serverProtocol = i;
|
||||
cls.serverProtocol = MSG_ReadLong( msg );
|
||||
|
||||
if( i != PROTOCOL_VERSION )
|
||||
Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION );
|
||||
if( cls.serverProtocol != PROTOCOL_VERSION )
|
||||
Host_Error( "Server use invalid protocol (%i should be %i)\n", cls.serverProtocol, PROTOCOL_VERSION );
|
||||
|
||||
cl.servercount = MSG_ReadLong( msg );
|
||||
cl.checksum = MSG_ReadLong( msg );
|
||||
cl.playernum = MSG_ReadByte( msg );
|
||||
cl.maxclients = MSG_ReadByte( msg );
|
||||
servercount = MSG_ReadLong( msg );
|
||||
checksum = MSG_ReadLong( msg );
|
||||
playernum = MSG_ReadByte( msg );
|
||||
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 );
|
||||
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 ();
|
||||
|
||||
// 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
|
||||
|
@ -805,15 +826,6 @@ 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 );
|
||||
|
@ -829,13 +841,11 @@ void CL_ParseServerData( sizebuf_t *msg )
|
|||
else if( !cls.demoplayback )
|
||||
Key_SetKeyDest( key_menu );
|
||||
|
||||
cl.viewentity = cl.playernum + 1; // always keep viewent an actual
|
||||
|
||||
// will be changed later
|
||||
cl.viewentity = cl.playernum + 1;
|
||||
gameui.globals->maxClients = cl.maxclients;
|
||||
Q_strncpy( gameui.globals->maptitle, clgame.maptitle, sizeof( gameui.globals->maptitle ));
|
||||
|
||||
if( !cls.changelevel && !cls.changedemo )
|
||||
CL_InitEdicts (); // re-arrange edicts
|
||||
CL_InitEdicts (); // re-arrange edicts
|
||||
|
||||
// get splash name
|
||||
if( cls.demoplayback && ( cls.demonum != -1 ))
|
||||
|
@ -2204,14 +2214,13 @@ ACTION MESSAGES
|
|||
=====================
|
||||
CL_ParseServerMessage
|
||||
|
||||
INTERNAL RESOURCE
|
||||
dispatch messages
|
||||
=====================
|
||||
*/
|
||||
void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||
{
|
||||
char *s;
|
||||
int i, cmd, param1, param2;
|
||||
size_t bufStart, playerbytes;
|
||||
int cmd, param1, param2;
|
||||
|
||||
cls_message_debug.parsing = true; // begin parsing
|
||||
starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
|
||||
|
@ -2304,18 +2313,10 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
|||
CL_ParseServerTime( msg );
|
||||
break;
|
||||
case svc_print:
|
||||
i = MSG_ReadByte( msg );
|
||||
MsgDev( D_INFO, "^5%s", MSG_ReadString( msg ));
|
||||
if( i == PRINT_CHAT )
|
||||
{
|
||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
S_StartLocalSound( "misc/talk.wav", VOL_NORM, false );
|
||||
else S_StartLocalSound( "common/menu2.wav", VOL_NORM, false );
|
||||
}
|
||||
break;
|
||||
case svc_stufftext:
|
||||
s = MSG_ReadString( msg );
|
||||
Cbuf_AddText( s );
|
||||
Cbuf_AddText( MSG_ReadString( msg ));
|
||||
break;
|
||||
case svc_setangle:
|
||||
CL_ParseSetAngle( msg );
|
||||
|
|
|
@ -1138,7 +1138,7 @@ static int DecalDepthCompare( const void *a, const void *b )
|
|||
// Input : *pList -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int R_CreateDecalList( decallist_t *pList, qboolean changelevel )
|
||||
int R_CreateDecalList( decallist_t *pList )
|
||||
{
|
||||
int total = 0;
|
||||
int i, depth;
|
||||
|
@ -1151,7 +1151,7 @@ int R_CreateDecalList( decallist_t *pList, qboolean changelevel )
|
|||
decal_t *pdecals;
|
||||
|
||||
// decal is in use and is not a custom decal
|
||||
if( decal->psurface == NULL || ( decal->flags & FDECAL_DONTSAVE ))
|
||||
if( decal->psurface == NULL || FBitSet( decal->flags, FDECAL_DONTSAVE ))
|
||||
continue;
|
||||
|
||||
// compute depth
|
||||
|
@ -1177,7 +1177,7 @@ int R_CreateDecalList( decallist_t *pList, qboolean changelevel )
|
|||
|
||||
if( clgame.drawFuncs.R_CreateStudioDecalList )
|
||||
{
|
||||
total += clgame.drawFuncs.R_CreateStudioDecalList( pList, total, changelevel );
|
||||
total += clgame.drawFuncs.R_CreateStudioDecalList( pList, total );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -344,16 +344,10 @@ COM_AddAppDirectoryToSearchPath
|
|||
*/
|
||||
void COM_AddAppDirectoryToSearchPath( const char *pszBaseDir, const char *appName )
|
||||
{
|
||||
string dir;
|
||||
|
||||
if( !pszBaseDir || !appName )
|
||||
{
|
||||
MsgDev( D_ERROR, "COM_AddDirectorySearchPath: bad directory or appname\n" );
|
||||
if( !COM_CheckString( pszBaseDir ))
|
||||
return;
|
||||
}
|
||||
|
||||
Q_snprintf( dir, sizeof( dir ), "%s/%s", pszBaseDir, appName );
|
||||
FS_AddGameDirectory( dir, FS_GAMEDIR_PATH );
|
||||
FS_AddGameDirectory( pszBaseDir, FS_GAMEDIR_PATH );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -289,15 +289,6 @@ typedef enum
|
|||
RD_PACKET
|
||||
} rdtype_t;
|
||||
|
||||
// game print level
|
||||
typedef enum
|
||||
{
|
||||
PRINT_LOW, // pickup messages
|
||||
PRINT_MEDIUM, // death messages
|
||||
PRINT_HIGH, // critical messages
|
||||
PRINT_CHAT, // chat messages
|
||||
} messagelevel_t;
|
||||
|
||||
#include "net_ws.h"
|
||||
|
||||
typedef struct host_redirect_s
|
||||
|
@ -766,7 +757,7 @@ float pfnTime( void );
|
|||
*/
|
||||
#define Z_Malloc( size ) Mem_Alloc( host.mempool, size )
|
||||
#define Z_Realloc( ptr, size ) Mem_Realloc( host.mempool, ptr, size )
|
||||
#define Z_Free( ptr ) if( ptr ) Mem_Free( ptr )
|
||||
#define Z_Free( ptr ) if( ptr != NULL ) Mem_Free( ptr )
|
||||
|
||||
//
|
||||
// crclib.c
|
||||
|
@ -853,9 +844,7 @@ qboolean CL_IsInConsole( void );
|
|||
qboolean CL_IsThirdPerson( void );
|
||||
qboolean CL_IsIntermission( void );
|
||||
qboolean CL_Initialized( void );
|
||||
qboolean CL_IsTimeDemo( void );
|
||||
char *CL_Userinfo( void );
|
||||
float CL_GetLerpFrac( void );
|
||||
void CL_CharEvent( int key );
|
||||
qboolean CL_DisableVisibility( void );
|
||||
int CL_PointContents( const vec3_t point );
|
||||
|
@ -868,15 +857,13 @@ struct pmtrace_s *PM_TraceLine( float *start, float *end, int flags, int usehull
|
|||
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
|
||||
void SV_StartMusic( const char *curtrack, const char *looptrack, long position );
|
||||
void SV_CreateDecal( struct sizebuf_s *msg, const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags, float scale );
|
||||
void SV_CreateStudioDecal( struct sizebuf_s *msg, const float *origin, const float *start, int decalIndex, int entityIndex, int modelIndex,
|
||||
int flags, struct modelstate_s *state );
|
||||
void SV_CreateStudioDecal( struct sizebuf_s *bf, const float *v0, const float *v1, int decal, int ent, int model, int flags, struct modelstate_s *s );
|
||||
void Log_Printf( const char *fmt, ... );
|
||||
struct sizebuf_s *SV_GetReliableDatagram( void );
|
||||
void SV_BroadcastCommand( const char *fmt, ... );
|
||||
void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char *start );
|
||||
qboolean SV_RestoreCustomDecal( struct decallist_s *entry, edict_t *pEdict, qboolean adjacent );
|
||||
void SV_BroadcastPrintf( struct sv_client_s *ignore, int level, char *fmt, ... );
|
||||
int R_CreateDecalList( struct decallist_s *pList, qboolean changelevel );
|
||||
void SV_BroadcastPrintf( struct sv_client_s *ignore, char *fmt, ... );
|
||||
int R_CreateDecalList( struct decallist_s *pList );
|
||||
void R_DecalRemoveAll( int texture );
|
||||
void R_ClearAllDecals( void );
|
||||
void R_ClearStaticEntities( void );
|
||||
|
@ -884,8 +871,6 @@ qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *posi
|
|||
struct cl_entity_s *CL_GetEntityByIndex( int index );
|
||||
struct player_info_s *CL_GetPlayerInfo( int playerIndex );
|
||||
void CL_ServerCommand( qboolean reliable, char *fmt, ... );
|
||||
void SV_ActivateServer( void );
|
||||
void SV_DeactivateServer( void );
|
||||
const char *CL_MsgInfo( int cmd );
|
||||
void SV_DrawDebugTriangles( void );
|
||||
void SV_DrawOrthoTriangles( void );
|
||||
|
@ -895,19 +880,22 @@ void CL_ExtraUpdate( void );
|
|||
int CL_GetMaxClients( void );
|
||||
int SV_GetMaxClients( void );
|
||||
qboolean CL_IsRecordDemo( void );
|
||||
qboolean CL_IsTimeDemo( void );
|
||||
qboolean CL_IsPlaybackDemo( void );
|
||||
qboolean CL_IsBackgroundDemo( void );
|
||||
qboolean CL_IsBackgroundMap( void );
|
||||
qboolean SV_Initialized( void );
|
||||
qboolean CL_LoadProgs( const char *name );
|
||||
qboolean SV_GetComment( const char *savename, char *comment );
|
||||
qboolean SV_NewGame( const char *mapName, qboolean loadGame );
|
||||
void SV_ClipPMoveToEntity( struct physent_s *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, struct pmtrace_s *tr );
|
||||
void CL_ClipPMoveToEntity( struct physent_s *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, struct pmtrace_s *tr );
|
||||
void CL_Particle( const vec3_t origin, int color, float life, int zpos, int zvel ); // debug thing
|
||||
void SV_LevelInit( const char *pMapName, char const *pOldLevel, char const *pLandmarkName, qboolean loadGame );
|
||||
qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean background );
|
||||
void SV_SysError( const char *error_string );
|
||||
qboolean SV_LoadGame( const char *pName );
|
||||
void SV_ShutdownGame( void );
|
||||
void SV_ExecLoadLevel( void );
|
||||
void SV_ExecLoadGame( void );
|
||||
void SV_ExecChangeLevel( void );
|
||||
void SV_ClearSaveDir( void );
|
||||
void SV_InitGameProgs( void );
|
||||
void SV_FreeGameProgs( void );
|
||||
|
|
|
@ -79,12 +79,12 @@ static qboolean Cvar_UpdateInfo( convar_t *var, const char *value, qboolean noti
|
|||
if( FBitSet( var->flags, FCVAR_PROTECTED ))
|
||||
{
|
||||
Log_Printf( "Server cvar \"%s\" = \"%s\"\n", var->name, "***PROTECTED***" );
|
||||
SV_BroadcastPrintf( NULL, PRINT_HIGH, "\"%s\" changed to \"%s\"\n", var->name, "***PROTECTED***" );
|
||||
SV_BroadcastPrintf( NULL, "\"%s\" changed to \"%s\"\n", var->name, "***PROTECTED***" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Log_Printf( "Server cvar \"%s\" = \"%s\"\n", var->name, value );
|
||||
SV_BroadcastPrintf( NULL, PRINT_HIGH, "\"%s\" changed to \"%s\"\n", var->name, value );
|
||||
SV_BroadcastPrintf( NULL, "\"%s\" changed to \"%s\"\n", var->name, value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ int Host_CompareFileTime( long ft1, long ft2 )
|
|||
|
||||
void Host_ShutdownServer( void )
|
||||
{
|
||||
if( !SV_Active( )) return;
|
||||
if( !SV_Initialized( )) return;
|
||||
Q_strncpy( host.finalmsg, "Server was killed", MAX_STRING );
|
||||
SV_Shutdown( false );
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ void Host_EndGame( qboolean abort, const char *message, ... )
|
|||
|
||||
MsgDev( D_INFO, "Host_EndGame: %s\n", string );
|
||||
|
||||
if( SV_Active( ))
|
||||
if( SV_Initialized( ))
|
||||
{
|
||||
Q_snprintf( host.finalmsg, sizeof( host.finalmsg ), "Host_EndGame: %s", string );
|
||||
SV_Shutdown( false );
|
||||
|
@ -442,7 +442,7 @@ void Host_RestartDecals( void )
|
|||
|
||||
// g-cont. add space for studiodecals if present
|
||||
host.decalList = (decallist_t *)Z_Malloc( sizeof( decallist_t ) * MAX_RENDER_DECALS * 2 );
|
||||
host.numdecals = R_CreateDecalList( host.decalList, false );
|
||||
host.numdecals = R_CreateDecalList( host.decalList );
|
||||
|
||||
// remove decals from map
|
||||
R_ClearAllDecals();
|
||||
|
|
|
@ -14,29 +14,20 @@ GNU General Public License for more details.
|
|||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "netchan.h"
|
||||
#include "protocol.h"
|
||||
#include "mod_local.h"
|
||||
#include "mathlib.h"
|
||||
#include "input.h"
|
||||
#include "features.h"
|
||||
#include "render_api.h" // decallist_t
|
||||
|
||||
void COM_InitHostState( void )
|
||||
{
|
||||
memset( GameState, 0, sizeof( game_status_t ));
|
||||
GameState->curstate = STATE_RUNFRAME;
|
||||
GameState->nextstate = STATE_RUNFRAME;
|
||||
}
|
||||
|
||||
static void HostState_SetState( host_state_t newState, qboolean clearNext )
|
||||
static void Host_SetState( host_state_t newState, qboolean clearNext )
|
||||
{
|
||||
if( clearNext )
|
||||
GameState->nextstate = newState;
|
||||
GameState->curstate = newState;
|
||||
}
|
||||
|
||||
static void HostState_SetNextState( host_state_t nextState )
|
||||
static void Host_SetNextState( host_state_t nextState )
|
||||
{
|
||||
ASSERT( GameState->curstate == STATE_RUNFRAME );
|
||||
GameState->nextstate = nextState;
|
||||
|
@ -44,8 +35,11 @@ static void HostState_SetNextState( host_state_t nextState )
|
|||
|
||||
void COM_NewGame( char const *pMapName )
|
||||
{
|
||||
if( GameState->nextstate != STATE_RUNFRAME )
|
||||
return;
|
||||
|
||||
Q_strncpy( GameState->levelName, pMapName, sizeof( GameState->levelName ));
|
||||
HostState_SetNextState( STATE_LOAD_LEVEL );
|
||||
Host_SetNextState( STATE_LOAD_LEVEL );
|
||||
|
||||
GameState->backgroundMap = false;
|
||||
GameState->landmarkName[0] = 0;
|
||||
|
@ -54,8 +48,11 @@ void COM_NewGame( char const *pMapName )
|
|||
|
||||
void COM_LoadLevel( char const *pMapName, qboolean background )
|
||||
{
|
||||
if( GameState->nextstate != STATE_RUNFRAME )
|
||||
return;
|
||||
|
||||
Q_strncpy( GameState->levelName, pMapName, sizeof( GameState->levelName ));
|
||||
HostState_SetNextState( STATE_LOAD_LEVEL );
|
||||
Host_SetNextState( STATE_LOAD_LEVEL );
|
||||
|
||||
GameState->backgroundMap = background;
|
||||
GameState->landmarkName[0] = 0;
|
||||
|
@ -64,8 +61,11 @@ void COM_LoadLevel( char const *pMapName, qboolean background )
|
|||
|
||||
void COM_LoadGame( char const *pMapName )
|
||||
{
|
||||
if( GameState->nextstate != STATE_RUNFRAME )
|
||||
return;
|
||||
|
||||
Q_strncpy( GameState->levelName, pMapName, sizeof( GameState->levelName ));
|
||||
HostState_SetNextState( STATE_LOAD_GAME );
|
||||
Host_SetNextState( STATE_LOAD_GAME );
|
||||
GameState->backgroundMap = false;
|
||||
GameState->newGame = false;
|
||||
GameState->loadGame = true;
|
||||
|
@ -73,6 +73,9 @@ void COM_LoadGame( char const *pMapName )
|
|||
|
||||
void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName )
|
||||
{
|
||||
if( GameState->nextstate != STATE_RUNFRAME )
|
||||
return;
|
||||
|
||||
Q_strncpy( GameState->levelName, pNewLevel, sizeof( GameState->levelName ));
|
||||
|
||||
if( COM_CheckString( pLandmarkName ))
|
||||
|
@ -86,68 +89,27 @@ void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName )
|
|||
GameState->loadGame = false;
|
||||
}
|
||||
|
||||
HostState_SetNextState( STATE_CHANGELEVEL );
|
||||
Host_SetNextState( STATE_CHANGELEVEL );
|
||||
GameState->newGame = false;
|
||||
}
|
||||
|
||||
void HostState_LoadLevel( void )
|
||||
void Host_ShutdownGame( void )
|
||||
{
|
||||
if( SV_SpawnServer( GameState->levelName, NULL, GameState->backgroundMap ))
|
||||
{
|
||||
SV_LevelInit( GameState->levelName, NULL, NULL, false );
|
||||
SV_ActivateServer ();
|
||||
}
|
||||
|
||||
HostState_SetState( STATE_RUNFRAME, true );
|
||||
}
|
||||
|
||||
void HostState_LoadGame( void )
|
||||
{
|
||||
if( SV_SpawnServer( GameState->levelName, NULL, false ))
|
||||
{
|
||||
SV_LevelInit( GameState->levelName, NULL, NULL, true );
|
||||
SV_ActivateServer ();
|
||||
}
|
||||
|
||||
HostState_SetState( STATE_RUNFRAME, true );
|
||||
}
|
||||
|
||||
void HostState_ChangeLevel( void )
|
||||
{
|
||||
SV_ChangeLevel( GameState->loadGame, GameState->levelName, GameState->landmarkName );
|
||||
HostState_SetState( STATE_RUNFRAME, true );
|
||||
}
|
||||
|
||||
void HostState_ShutdownGame( void )
|
||||
{
|
||||
if( !GameState->loadGame )
|
||||
SV_ClearSaveDir();
|
||||
|
||||
S_StopBackgroundTrack();
|
||||
|
||||
if( GameState->newGame )
|
||||
{
|
||||
Host_EndGame( false, DEFAULT_ENDGAME_MESSAGE );
|
||||
}
|
||||
else
|
||||
{
|
||||
S_StopAllSounds( true );
|
||||
SV_DeactivateServer();
|
||||
}
|
||||
SV_ShutdownGame();
|
||||
|
||||
switch( GameState->nextstate )
|
||||
{
|
||||
case STATE_LOAD_GAME:
|
||||
case STATE_LOAD_LEVEL:
|
||||
HostState_SetState( GameState->nextstate, true );
|
||||
Host_SetState( GameState->nextstate, true );
|
||||
break;
|
||||
default:
|
||||
HostState_SetState( STATE_RUNFRAME, true );
|
||||
Host_SetState( STATE_RUNFRAME, true );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HostState_Run( float time )
|
||||
void Host_RunFrame( float time )
|
||||
{
|
||||
// engine main frame
|
||||
Host_Frame( time );
|
||||
|
@ -161,14 +123,14 @@ void HostState_Run( float time )
|
|||
SCR_BeginLoadingPlaque( GameState->backgroundMap );
|
||||
// intentionally fallthrough
|
||||
case STATE_GAME_SHUTDOWN:
|
||||
HostState_SetState( STATE_GAME_SHUTDOWN, false );
|
||||
Host_SetState( STATE_GAME_SHUTDOWN, false );
|
||||
break;
|
||||
case STATE_CHANGELEVEL:
|
||||
SCR_BeginLoadingPlaque( false );
|
||||
HostState_SetState( GameState->nextstate, true );
|
||||
Host_SetState( GameState->nextstate, true );
|
||||
break;
|
||||
default:
|
||||
HostState_SetState( STATE_RUNFRAME, true );
|
||||
Host_SetState( STATE_RUNFRAME, true );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -185,19 +147,22 @@ void COM_Frame( float time )
|
|||
switch( GameState->curstate )
|
||||
{
|
||||
case STATE_LOAD_LEVEL:
|
||||
HostState_LoadLevel();
|
||||
SV_ExecLoadLevel();
|
||||
Host_SetState( STATE_RUNFRAME, true );
|
||||
break;
|
||||
case STATE_LOAD_GAME:
|
||||
HostState_LoadGame();
|
||||
SV_ExecLoadGame();
|
||||
Host_SetState( STATE_RUNFRAME, true );
|
||||
break;
|
||||
case STATE_CHANGELEVEL:
|
||||
HostState_ChangeLevel();
|
||||
SV_ExecChangeLevel();
|
||||
Host_SetState( STATE_RUNFRAME, true );
|
||||
break;
|
||||
case STATE_RUNFRAME:
|
||||
HostState_Run( time );
|
||||
Host_RunFrame( time );
|
||||
break;
|
||||
case STATE_GAME_SHUTDOWN:
|
||||
HostState_ShutdownGame();
|
||||
Host_ShutdownGame();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,6 @@ static void Mod_FreeModel( model_t *mod )
|
|||
if( !mod || !mod->name[0] )
|
||||
return;
|
||||
|
||||
Msg( "release %s\n", mod->name );
|
||||
Mod_FreeUserData( mod );
|
||||
|
||||
// select the properly unloader
|
||||
|
@ -479,8 +478,6 @@ void Mod_FreeUnused( void )
|
|||
model_t *mod;
|
||||
int i;
|
||||
|
||||
Msg( "Mod_FreeUnused()\n" );
|
||||
|
||||
for( i = 0, mod = mod_known; i < mod_numknown; i++, mod++ )
|
||||
{
|
||||
if( mod->needload == NL_UNREFERENCED )
|
||||
|
|
|
@ -96,6 +96,12 @@ sizebuf_t net_message;
|
|||
byte *net_mempool;
|
||||
byte net_message_buffer[NET_MAX_MESSAGE];
|
||||
|
||||
const char *ns_strings[NS_COUNT] =
|
||||
{
|
||||
"Client",
|
||||
"Server",
|
||||
};
|
||||
|
||||
/*
|
||||
===============
|
||||
Netchan_Init
|
||||
|
@ -714,7 +720,7 @@ void Netchan_CheckForCompletion( netchan_t *chan, int stream, int intotalbuffers
|
|||
if( c == intotalbuffers )
|
||||
{
|
||||
chan->incomingready[stream] = true;
|
||||
MsgDev( D_NOTE, "\nincoming is complete %i bytes waiting\n", size );
|
||||
MsgDev( D_NOTE, "\n%s: incoming is complete %i bytes waiting\n", ns_strings[chan->sock], size );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ typedef struct physics_interface_s
|
|||
// called through save\restore process
|
||||
void (*pfnCreateEntitiesInTransitionList)( SAVERESTOREDATA*, int levelMask );
|
||||
// called through save\restore process
|
||||
void (*pfnCreateEntitiesInRestoreList)( SAVERESTOREDATA*, int createPlayers );
|
||||
void (*pfnCreateEntitiesInRestoreList)( SAVERESTOREDATA* );
|
||||
// allocate custom string (e.g. using user implementation of stringtable, not engine strings)
|
||||
string_t (*pfnAllocString)( const char *szValue );
|
||||
// make custom string (e.g. using user implementation of stringtable, not engine strings)
|
||||
|
|
|
@ -246,8 +246,6 @@ typedef struct sv_client_s
|
|||
|
||||
edict_t *edict; // EDICT_NUM(clientnum+1)
|
||||
edict_t *pViewEntity; // svc_setview member
|
||||
int messagelevel; // for filtering printed messages
|
||||
|
||||
edict_t *viewentity[MAX_VIEWENTS]; // list of portal cameras in player PVS
|
||||
int num_viewents; // num of portal cameras that can merge PVS
|
||||
|
||||
|
@ -485,10 +483,11 @@ void Master_Packet( void );
|
|||
//
|
||||
// sv_init.c
|
||||
//
|
||||
void SV_ActivateServer( void );
|
||||
void SV_LevelInit( const char *pMapName, char const *pOldLevel, char const *pLandmarkName, qboolean loadGame );
|
||||
void SV_ActivateServer( int runPhysics );
|
||||
qboolean SV_SpawnServer( const char *server, const char *startspot, qboolean background );
|
||||
model_t *SV_ModelHandle( int modelindex );
|
||||
void SV_DeactivateServer( void );
|
||||
char *SV_EntityScript( void );
|
||||
|
||||
//
|
||||
// sv_phys.c
|
||||
|
@ -519,8 +518,8 @@ void SV_WaterMove( edict_t *ent );
|
|||
// sv_send.c
|
||||
//
|
||||
void SV_SendClientMessages( void );
|
||||
void SV_ClientPrintf( sv_client_t *cl, int level, char *fmt, ... );
|
||||
void SV_BroadcastPrintf( sv_client_t *ignore, int level, char *fmt, ... );
|
||||
void SV_ClientPrintf( sv_client_t *cl, char *fmt, ... );
|
||||
void SV_BroadcastPrintf( sv_client_t *ignore, char *fmt, ... );
|
||||
void SV_BroadcastCommand( const char *fmt, ... );
|
||||
|
||||
//
|
||||
|
@ -536,6 +535,7 @@ const char *SV_GetClientIDString( sv_client_t *cl );
|
|||
void SV_FullClientUpdate( sv_client_t *cl, sizebuf_t *msg );
|
||||
void SV_FullUpdateMovevars( sv_client_t *cl, sizebuf_t *msg );
|
||||
void SV_GetPlayerStats( sv_client_t *cl, int *ping, int *packet_loss );
|
||||
void SV_SendServerdata( sizebuf_t *msg, sv_client_t *cl );
|
||||
qboolean SV_ClientConnect( edict_t *ent, char *userinfo );
|
||||
void SV_ClientThink( sv_client_t *cl, usercmd_t *cmd );
|
||||
void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg );
|
||||
|
@ -543,6 +543,7 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg );
|
|||
edict_t *SV_FakeConnect( const char *netname );
|
||||
void SV_ExecuteClientCommand( sv_client_t *cl, char *s );
|
||||
void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed );
|
||||
void SV_BuildReconnect( sizebuf_t *msg );
|
||||
qboolean SV_IsPlayerIndex( int idx );
|
||||
int SV_CalcPing( sv_client_t *cl );
|
||||
void SV_InitClientMove( void );
|
||||
|
@ -572,9 +573,9 @@ int SV_TransferConsistencyInfo( void );
|
|||
//
|
||||
// sv_frame.c
|
||||
//
|
||||
void SV_InactivateClients( void );
|
||||
void SV_WriteFrameToClient( sv_client_t *client, sizebuf_t *msg );
|
||||
void SV_BuildClientFrame( sv_client_t *client );
|
||||
void SV_InactivateClients( void );
|
||||
void SV_SendMessagesToAll( void );
|
||||
void SV_SkipUpdates( void );
|
||||
|
||||
|
@ -625,7 +626,7 @@ char *SV_Localinfo( void );
|
|||
|
||||
_inline edict_t *SV_EDICT_NUM( int n, const char * file, const int line )
|
||||
{
|
||||
if((n >= 0) && (n < svgame.globals->maxEntities))
|
||||
if((n >= 0) && (n < GI->max_edicts))
|
||||
return svgame.edicts + n;
|
||||
Host_Error( "SV_EDICT_NUM: bad number %i (called at %s:%i)\n", n, file, line );
|
||||
return NULL;
|
||||
|
@ -645,10 +646,12 @@ void SV_ServerLog_f( sv_client_t *cl );
|
|||
void SV_ClearSaveDir( void );
|
||||
void SV_SaveGame( const char *pName );
|
||||
qboolean SV_LoadGame( const char *pName );
|
||||
int SV_LoadGameState( char const *level, qboolean createPlayers );
|
||||
int SV_LoadGameState( char const *level, qboolean changelevel );
|
||||
void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char *start );
|
||||
void SV_LoadAdjacentEnts( const char *pOldLevel, const char *pLandmarkName );
|
||||
const char *SV_GetLatestSave( void );
|
||||
void SV_InitSaveRestore( void );
|
||||
void SV_ClearGameState( void );
|
||||
|
||||
//
|
||||
// sv_pmove.c
|
||||
|
|
|
@ -535,10 +535,7 @@ qboolean SV_ClientConnect( edict_t *ent, char *userinfo )
|
|||
char *pszName, *pszAddress;
|
||||
char szRejectReason[MAX_INFO_STRING];
|
||||
|
||||
// make sure we start with known default
|
||||
if( !sv.loadgame ) ent->v.flags = 0;
|
||||
szRejectReason[0] = '\0';
|
||||
|
||||
pszName = Info_ValueForKey( userinfo, "name" );
|
||||
pszAddress = Info_ValueForKey( userinfo, "ip" );
|
||||
|
||||
|
@ -642,7 +639,6 @@ void SV_FlushRedirect( netadr_t adr, int dest, char *buf )
|
|||
case RD_CLIENT:
|
||||
if( !svs.currentPlayer ) return; // client not set
|
||||
MSG_BeginServerCmd( &svs.currentPlayer->netchan.message, svc_print );
|
||||
MSG_WriteByte( &svs.currentPlayer->netchan.message, PRINT_HIGH );
|
||||
MSG_WriteString( &svs.currentPlayer->netchan.message, buf );
|
||||
break;
|
||||
case RD_NONE:
|
||||
|
@ -1204,35 +1200,7 @@ void SV_PutClientInServer( sv_client_t *cl )
|
|||
|
||||
MSG_Init( &msg, "Spawn", msg_buf, sizeof( msg_buf ));
|
||||
|
||||
if( !sv.loadgame )
|
||||
{
|
||||
if( Q_atoi( Info_ValueForKey( cl->userinfo, "hltv" )))
|
||||
SetBits( cl->flags, FCL_HLTV_PROXY );
|
||||
|
||||
if( FBitSet( cl->flags, FCL_HLTV_PROXY ))
|
||||
SetBits( ent->v.flags, FL_PROXY );
|
||||
else ent->v.flags = 0;
|
||||
|
||||
ent->v.netname = MAKE_STRING( cl->name );
|
||||
ent->v.colormap = NUM_FOR_EDICT( ent ); // ???
|
||||
|
||||
// fisrt entering
|
||||
svgame.globals->time = sv.time;
|
||||
svgame.dllFuncs.pfnClientPutInServer( ent );
|
||||
|
||||
if( sv.background ) // don't attack player in background mode
|
||||
SetBits( ent->v.flags, FL_GODMODE|FL_NOTARGET );
|
||||
|
||||
cl->pViewEntity = NULL; // reset pViewEntity
|
||||
|
||||
if( svgame.globals->cdAudioTrack )
|
||||
{
|
||||
MSG_BeginServerCmd( &msg, svc_stufftext );
|
||||
MSG_WriteString( &msg, va( "cd loop %3d\n", svgame.globals->cdAudioTrack ));
|
||||
svgame.globals->cdAudioTrack = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
if( sv.loadgame )
|
||||
{
|
||||
// NOTE: we needs to setup angles on restore here
|
||||
if( ent->v.fixangle == 1 )
|
||||
|
@ -1275,6 +1243,37 @@ void SV_PutClientInServer( sv_client_t *cl )
|
|||
if( sv.viewentity > 0 && sv.viewentity < GI->max_edicts )
|
||||
cl->pViewEntity = EDICT_NUM( sv.viewentity );
|
||||
else cl->pViewEntity = NULL;
|
||||
|
||||
sv.loadgame = false;
|
||||
sv.paused = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( Q_atoi( Info_ValueForKey( cl->userinfo, "hltv" )))
|
||||
SetBits( cl->flags, FCL_HLTV_PROXY );
|
||||
|
||||
if( FBitSet( cl->flags, FCL_HLTV_PROXY ))
|
||||
SetBits( ent->v.flags, FL_PROXY );
|
||||
else ent->v.flags = 0;
|
||||
|
||||
ent->v.netname = MAKE_STRING( cl->name );
|
||||
ent->v.colormap = NUM_FOR_EDICT( ent ); // ???
|
||||
|
||||
// fisrt entering
|
||||
svgame.globals->time = sv.time;
|
||||
svgame.dllFuncs.pfnClientPutInServer( ent );
|
||||
|
||||
if( sv.background ) // don't attack player in background mode
|
||||
SetBits( ent->v.flags, FL_GODMODE|FL_NOTARGET );
|
||||
|
||||
cl->pViewEntity = NULL; // reset pViewEntity
|
||||
|
||||
if( svgame.globals->cdAudioTrack )
|
||||
{
|
||||
MSG_BeginServerCmd( &msg, svc_stufftext );
|
||||
MSG_WriteString( &msg, va( "cd loop %3d\n", svgame.globals->cdAudioTrack ));
|
||||
svgame.globals->cdAudioTrack = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// enable dev-mode to prevent crash cheat-protecting from Invasion mod
|
||||
|
@ -1314,11 +1313,6 @@ void SV_PutClientInServer( sv_client_t *cl )
|
|||
Netchan_CreateFragments( &cl->netchan, &msg );
|
||||
Netchan_FragSend( &cl->netchan );
|
||||
}
|
||||
|
||||
// clear any temp states
|
||||
sv.changelevel = false;
|
||||
sv.loadgame = false;
|
||||
sv.paused = false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1351,13 +1345,27 @@ void SV_TogglePause( const char *msg )
|
|||
|
||||
sv.paused ^= 1;
|
||||
|
||||
if( msg ) SV_BroadcastPrintf( NULL, PRINT_HIGH, "%s", msg );
|
||||
if( COM_CheckString( msg ))
|
||||
SV_BroadcastPrintf( NULL, "%s", msg );
|
||||
|
||||
// send notification to all clients
|
||||
MSG_BeginServerCmd( &sv.reliable_datagram, svc_setpause );
|
||||
MSG_WriteOneBit( &sv.reliable_datagram, sv.paused );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_SendReconnect
|
||||
|
||||
Tell all the clients that the server is changing levels
|
||||
================
|
||||
*/
|
||||
void SV_BuildReconnect( sizebuf_t *msg )
|
||||
{
|
||||
MSG_BeginServerCmd( msg, svc_stufftext );
|
||||
MSG_WriteString( msg, "reconnect\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_WriteDeltaDescriptionToClient
|
||||
|
@ -1389,20 +1397,30 @@ This will be sent on the initial connection and upon each server load.
|
|||
*/
|
||||
void SV_SendServerdata( sizebuf_t *msg, sv_client_t *cl )
|
||||
{
|
||||
string message;
|
||||
int i;
|
||||
|
||||
// Only send this message to developer console, or multiplayer clients.
|
||||
if(( host.developer ) || ( svs.maxclients > 1 ))
|
||||
{
|
||||
MSG_BeginServerCmd( msg, svc_print );
|
||||
Q_snprintf( message, sizeof( message ), "%c\nBUILD %d SERVER (%i CRC)\nServer # %i\n", 2, Q_buildnum(), 0, svs.spawncount );
|
||||
MSG_WriteString( msg, message );
|
||||
}
|
||||
|
||||
// send the serverdata
|
||||
MSG_BeginServerCmd( msg, svc_serverdata );
|
||||
MSG_WriteLong( msg, PROTOCOL_VERSION );
|
||||
MSG_WriteLong( msg, svs.spawncount );
|
||||
MSG_WriteLong( msg, sv.worldmapCRC );
|
||||
MSG_WriteByte( msg, cl - svs.clients );
|
||||
MSG_WriteByte( msg, svgame.globals->maxClients );
|
||||
MSG_WriteWord( msg, svgame.globals->maxEntities );
|
||||
MSG_WriteByte( msg, svs.maxclients );
|
||||
MSG_WriteWord( msg, GI->max_edicts );
|
||||
MSG_WriteWord( msg, MAX_MODELS );
|
||||
MSG_WriteString( msg, sv.name );
|
||||
MSG_WriteString( msg, STRING( EDICT_NUM( 0 )->v.message )); // Map Message
|
||||
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 );
|
||||
|
||||
|
@ -1418,6 +1436,21 @@ void SV_SendServerdata( sizebuf_t *msg, sv_client_t *cl )
|
|||
|
||||
// now client know delta and can reading encoded messages
|
||||
SV_FullUpdateMovevars( cl, msg );
|
||||
|
||||
// send the user messages registration
|
||||
for( i = 1; i < MAX_USER_MESSAGES && svgame.msg[i].name[0]; i++ )
|
||||
SV_SendUserReg( msg, &svgame.msg[i] );
|
||||
|
||||
for( i = 0; i < MAX_LIGHTSTYLES; i++ )
|
||||
{
|
||||
if( !sv.lightstyles[i].pattern[0] )
|
||||
continue; // unused style
|
||||
|
||||
MSG_BeginServerCmd( msg, svc_lightstyle );
|
||||
MSG_WriteByte( msg, i ); // stylenum
|
||||
MSG_WriteString( msg, sv.lightstyles[i].pattern );
|
||||
MSG_WriteFloat( msg, sv.lightstyles[i].time );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1453,21 +1486,6 @@ void SV_New_f( sv_client_t *cl )
|
|||
// send the serverdata
|
||||
SV_SendServerdata( &msg, cl );
|
||||
|
||||
// send the user messages registration
|
||||
for( i = 1; i < MAX_USER_MESSAGES && svgame.msg[i].name[0]; i++ )
|
||||
SV_SendUserReg( &msg, &svgame.msg[i] );
|
||||
|
||||
for( i = 0; i < MAX_LIGHTSTYLES; i++ )
|
||||
{
|
||||
if( !sv.lightstyles[i].pattern[0] )
|
||||
continue; // unused style
|
||||
|
||||
MSG_BeginServerCmd( &msg, svc_lightstyle );
|
||||
MSG_WriteByte( &msg, i ); // stylenum
|
||||
MSG_WriteString( &msg, sv.lightstyles[i].pattern );
|
||||
MSG_WriteFloat( &msg, sv.lightstyles[i].time );
|
||||
}
|
||||
|
||||
// server info string
|
||||
MSG_BeginServerCmd( &msg, svc_stufftext );
|
||||
MSG_WriteString( &msg, va( "fullserverinfo \"%s\"\n", SV_Serverinfo( )));
|
||||
|
@ -1662,13 +1680,13 @@ void SV_Pause_f( sv_client_t *cl )
|
|||
|
||||
if( !sv_pausable->value )
|
||||
{
|
||||
SV_ClientPrintf( cl, PRINT_HIGH, "Pause not allowed.\n" );
|
||||
SV_ClientPrintf( cl, "Pause not allowed.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( FBitSet( cl->flags, FCL_HLTV_PROXY ))
|
||||
{
|
||||
SV_ClientPrintf( cl, PRINT_HIGH, "Spectators can not pause.\n" );
|
||||
SV_ClientPrintf( cl, "Spectators can not pause.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1753,19 +1771,18 @@ void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo )
|
|||
if( Q_strlen( val ))
|
||||
cl->netchan.rate = bound( MIN_RATE, Q_atoi( val ), MAX_RATE );
|
||||
else cl->netchan.rate = DEFAULT_RATE;
|
||||
|
||||
// msg command
|
||||
val = Info_ValueForKey( cl->userinfo, "msg" );
|
||||
if( Q_strlen( val )) cl->messagelevel = Q_atoi( val );
|
||||
|
||||
// movement prediction
|
||||
if( Q_atoi( Info_ValueForKey( cl->userinfo, "cl_nopred" )))
|
||||
ClearBits( cl->flags, FCL_PREDICT_MOVEMENT );
|
||||
else SetBits( cl->flags, FCL_PREDICT_MOVEMENT );
|
||||
|
||||
// lag compensation
|
||||
if( Q_atoi( Info_ValueForKey( cl->userinfo, "cl_lc" )))
|
||||
SetBits( cl->flags, FCL_LAG_COMPENSATION );
|
||||
else ClearBits( cl->flags, FCL_LAG_COMPENSATION );
|
||||
|
||||
// weapon perdiction
|
||||
if( Q_atoi( Info_ValueForKey( cl->userinfo, "cl_lw" )))
|
||||
SetBits( cl->flags, FCL_LOCAL_WEAPONS );
|
||||
else ClearBits( cl->flags, FCL_LOCAL_WEAPONS );
|
||||
|
@ -1830,13 +1847,37 @@ static void SV_Noclip_f( sv_client_t *cl )
|
|||
|
||||
if( pEntity->v.movetype != MOVETYPE_NOCLIP )
|
||||
{
|
||||
SV_ClientPrintf( cl, "noclip ON\n" );
|
||||
pEntity->v.movetype = MOVETYPE_NOCLIP;
|
||||
SV_ClientPrintf( cl, PRINT_HIGH, "noclip ON\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
SV_ClientPrintf( cl, "noclip OFF\n" );
|
||||
pEntity->v.movetype = MOVETYPE_WALK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_Fly_f
|
||||
==================
|
||||
*/
|
||||
static void SV_Fly_f( sv_client_t *cl )
|
||||
{
|
||||
edict_t *pEntity = cl->edict;
|
||||
|
||||
if( !Cvar_VariableInteger( "sv_cheats" ) || sv.background )
|
||||
return;
|
||||
|
||||
if( pEntity->v.movetype != MOVETYPE_FLY )
|
||||
{
|
||||
SV_ClientPrintf( cl, "flymode ON\n" );
|
||||
pEntity->v.movetype = MOVETYPE_FLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
SV_ClientPrintf( cl, "flymode OFF\n" );
|
||||
pEntity->v.movetype = MOVETYPE_WALK;
|
||||
SV_ClientPrintf( cl, PRINT_HIGH, "noclip OFF\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1855,8 +1896,8 @@ static void SV_Godmode_f( sv_client_t *cl )
|
|||
pEntity->v.flags = pEntity->v.flags ^ FL_GODMODE;
|
||||
|
||||
if( !FBitSet( pEntity->v.flags, FL_GODMODE ))
|
||||
SV_ClientPrintf( cl, PRINT_HIGH, "godmode OFF\n" );
|
||||
else SV_ClientPrintf( cl, PRINT_HIGH, "godmode ON\n" );
|
||||
SV_ClientPrintf( cl, "godmode OFF\n" );
|
||||
else SV_ClientPrintf( cl, "godmode ON\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1874,8 +1915,8 @@ static void SV_Notarget_f( sv_client_t *cl )
|
|||
pEntity->v.flags = pEntity->v.flags ^ FL_NOTARGET;
|
||||
|
||||
if( !FBitSet( pEntity->v.flags, FL_NOTARGET ))
|
||||
SV_ClientPrintf( cl, PRINT_HIGH, "notarget OFF\n" );
|
||||
else SV_ClientPrintf( cl, PRINT_HIGH, "notarget ON\n" );
|
||||
SV_ClientPrintf( cl, "notarget OFF\n" );
|
||||
else SV_ClientPrintf( cl, "notarget ON\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2013,7 +2054,7 @@ void SV_Spawn_f( sv_client_t *cl )
|
|||
{
|
||||
MSG_BeginServerCmd( &sv.reliable_datagram, svc_setpause );
|
||||
MSG_WriteByte( &sv.reliable_datagram, sv.paused );
|
||||
SV_ClientPrintf( cl, PRINT_HIGH, "Server is paused.\n" );
|
||||
SV_ClientPrintf( cl, "Server is paused.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2037,6 +2078,7 @@ void SV_Begin_f( sv_client_t *cl )
|
|||
ucmd_t ucmds[] =
|
||||
{
|
||||
{ "new", SV_New_f },
|
||||
{ "fly", SV_Fly_f },
|
||||
{ "god", SV_Godmode_f },
|
||||
{ "begin", SV_Begin_f },
|
||||
{ "spawn", SV_Spawn_f },
|
||||
|
@ -2278,7 +2320,7 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
|
|||
cl->packet_loss = packet_loss;
|
||||
|
||||
// check for pause or frozen
|
||||
if( sv.paused || sv.loadgame || sv.background || !CL_IsInGame() || SV_PlayerIsFrozen( player ))
|
||||
if( sv.paused || !CL_IsInGame() || SV_PlayerIsFrozen( player ))
|
||||
{
|
||||
for( i = 0; i < numcmds; i++ )
|
||||
{
|
||||
|
@ -2288,7 +2330,7 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
|
|||
cmds[i].upmove = 0;
|
||||
cmds[i].buttons = 0;
|
||||
|
||||
if( SV_PlayerIsFrozen( player ) || sv.background )
|
||||
if( SV_PlayerIsFrozen( player ))
|
||||
cmds[i].impulse = 0;
|
||||
|
||||
VectorCopy( cmds[i].viewangles, player->v.v_angle );
|
||||
|
|
|
@ -23,12 +23,12 @@ SV_ClientPrintf
|
|||
Sends text across to be displayed if the level passes
|
||||
=================
|
||||
*/
|
||||
void SV_ClientPrintf( sv_client_t *cl, int level, char *fmt, ... )
|
||||
void SV_ClientPrintf( sv_client_t *cl, char *fmt, ... )
|
||||
{
|
||||
char string[MAX_SYSPATH];
|
||||
va_list argptr;
|
||||
|
||||
if( level < cl->messagelevel || FBitSet( cl->flags, FCL_FAKECLIENT ))
|
||||
if( FBitSet( cl->flags, FCL_FAKECLIENT ))
|
||||
return;
|
||||
|
||||
va_start( argptr, fmt );
|
||||
|
@ -36,7 +36,6 @@ void SV_ClientPrintf( sv_client_t *cl, int level, char *fmt, ... )
|
|||
va_end( argptr );
|
||||
|
||||
MSG_BeginServerCmd( &cl->netchan.message, svc_print );
|
||||
MSG_WriteByte( &cl->netchan.message, level );
|
||||
MSG_WriteString( &cl->netchan.message, string );
|
||||
}
|
||||
|
||||
|
@ -47,7 +46,7 @@ SV_BroadcastPrintf
|
|||
Sends text to all active clients
|
||||
=================
|
||||
*/
|
||||
void SV_BroadcastPrintf( sv_client_t *ignore, int level, char *fmt, ... )
|
||||
void SV_BroadcastPrintf( sv_client_t *ignore, char *fmt, ... )
|
||||
{
|
||||
char string[MAX_SYSPATH];
|
||||
va_list argptr;
|
||||
|
@ -66,16 +65,17 @@ void SV_BroadcastPrintf( sv_client_t *ignore, int level, char *fmt, ... )
|
|||
|
||||
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ )
|
||||
{
|
||||
if( level < cl->messagelevel || FBitSet( cl->flags, FCL_FAKECLIENT ))
|
||||
if( FBitSet( cl->flags, FCL_FAKECLIENT ))
|
||||
continue;
|
||||
|
||||
if( cl == ignore || cl->state != cs_spawned )
|
||||
continue;
|
||||
|
||||
MSG_BeginServerCmd( &cl->netchan.message, svc_print );
|
||||
MSG_WriteByte( &cl->netchan.message, level );
|
||||
MSG_WriteString( &cl->netchan.message, string );
|
||||
}
|
||||
|
||||
MsgDev( D_REPORT, string );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -235,12 +235,7 @@ void SV_Map_f( void )
|
|||
if( !SV_ValidateMap( mapname, true ))
|
||||
return;
|
||||
|
||||
// changing singleplayer to multiplayer or back. refresh the player count
|
||||
if( FBitSet( sv_maxclients->flags, FCVAR_CHANGED ))
|
||||
Host_ShutdownServer();
|
||||
|
||||
Cvar_DirectSet( sv_hostmap, mapname );
|
||||
|
||||
COM_LoadLevel( mapname, false );
|
||||
}
|
||||
|
||||
|
@ -261,7 +256,7 @@ void SV_MapBackground_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
if( sv.state == ss_active && !sv.background )
|
||||
if( SV_Active() && !sv.background )
|
||||
{
|
||||
MsgDev( D_ERROR, "can't set background map while game is active\n" );
|
||||
return;
|
||||
|
@ -274,14 +269,10 @@ void SV_MapBackground_f( void )
|
|||
if( !SV_ValidateMap( mapname, false ))
|
||||
return;
|
||||
|
||||
Q_strncpy( host.finalmsg, "", MAX_STRING );
|
||||
SV_Shutdown( true );
|
||||
NET_Config( false ); // close network sockets
|
||||
|
||||
// reset all multiplayer cvars
|
||||
// background map is always run as singleplayer
|
||||
Cvar_FullSet( "maxplayers", "1", FCVAR_LATCH );
|
||||
Cvar_SetValue( "deathmatch", 0 );
|
||||
Cvar_SetValue( "coop", 0 );
|
||||
Cvar_FullSet( "deathmatch", "0", FCVAR_LATCH );
|
||||
Cvar_FullSet( "coop", "0", FCVAR_LATCH );
|
||||
|
||||
COM_LoadLevel( mapname, true );
|
||||
}
|
||||
|
@ -512,10 +503,17 @@ void SV_ChangeLevel_f( void )
|
|||
}
|
||||
|
||||
if( sv.background )
|
||||
{
|
||||
COM_LoadLevel( mapname, false );
|
||||
else if( c == 2 )
|
||||
COM_ChangeLevel( Cmd_Argv( 1 ), NULL );
|
||||
else COM_ChangeLevel( Cmd_Argv( 1 ), Cmd_Argv( 2 ));
|
||||
}
|
||||
else
|
||||
{
|
||||
// g-cont: inactivate clients to avoid fired "trigger_changelevel" multiple times
|
||||
SV_InactivateClients ();
|
||||
|
||||
if( c == 2 ) COM_ChangeLevel( Cmd_Argv( 1 ), NULL );
|
||||
else COM_ChangeLevel( Cmd_Argv( 1 ), Cmd_Argv( 2 ));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -570,8 +568,8 @@ void SV_Kick_f( void )
|
|||
}
|
||||
|
||||
Log_Printf( "Kick: \"%s<%i>\" was kicked\n", svs.currentPlayer->name, svs.currentPlayer->userid );
|
||||
SV_BroadcastPrintf( svs.currentPlayer, PRINT_HIGH, "%s was kicked\n", svs.currentPlayer->name );
|
||||
SV_ClientPrintf( svs.currentPlayer, PRINT_HIGH, "You were kicked from the game\n" );
|
||||
SV_BroadcastPrintf( svs.currentPlayer, "%s was kicked\n", svs.currentPlayer->name );
|
||||
SV_ClientPrintf( svs.currentPlayer, "You were kicked from the game\n" );
|
||||
SV_DropClient( svs.currentPlayer );
|
||||
}
|
||||
|
||||
|
@ -589,7 +587,7 @@ void SV_Kill_f( void )
|
|||
|
||||
if( svs.currentPlayer->edict->v.health <= 0.0f )
|
||||
{
|
||||
SV_ClientPrintf( svs.currentPlayer, PRINT_HIGH, "Can't suicide - already dead!\n");
|
||||
SV_ClientPrintf( svs.currentPlayer, "Can't suicide - already dead!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -678,9 +676,7 @@ SV_ConSay_f
|
|||
*/
|
||||
void SV_ConSay_f( void )
|
||||
{
|
||||
char *p, text[MAX_SYSPATH];
|
||||
sv_client_t *client;
|
||||
int i;
|
||||
char *p, text[MAX_SYSPATH];
|
||||
|
||||
if( Cmd_Argc() < 2 ) return;
|
||||
|
||||
|
@ -700,14 +696,7 @@ void SV_ConSay_f( void )
|
|||
}
|
||||
|
||||
Q_strncat( text, p, MAX_SYSPATH );
|
||||
|
||||
for( i = 0, client = svs.clients; i < svs.maxclients; i++, client++ )
|
||||
{
|
||||
if( client->state != cs_spawned )
|
||||
continue;
|
||||
|
||||
SV_ClientPrintf( client, PRINT_CHAT, "%s\n", text );
|
||||
}
|
||||
SV_BroadcastPrintf( NULL, "%s\n", text );
|
||||
Log_Printf( "Server say: \"%s\"\n", p );
|
||||
}
|
||||
|
||||
|
@ -849,8 +838,8 @@ void SV_PlayersOnly_f( void )
|
|||
sv.hostflags = sv.hostflags ^ SVF_PLAYERSONLY;
|
||||
|
||||
if( !FBitSet( sv.hostflags, SVF_PLAYERSONLY ))
|
||||
SV_BroadcastPrintf( NULL, PRINT_HIGH, "Resume server physic\n" );
|
||||
else SV_BroadcastPrintf( NULL, PRINT_HIGH, "Freeze server physic\n" );
|
||||
SV_BroadcastPrintf( NULL, "Resume game physic\n" );
|
||||
else SV_BroadcastPrintf( NULL, "Freeze game physic\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -871,8 +860,8 @@ void SV_EdictUsage_f( void )
|
|||
|
||||
active = pfnNumberOfEntities();
|
||||
Msg( "%5i edicts is used\n", active );
|
||||
Msg( "%5i edicts is free\n", svgame.globals->maxEntities - active );
|
||||
Msg( "%5i total\n", svgame.globals->maxEntities );
|
||||
Msg( "%5i edicts is free\n", GI->max_edicts - active );
|
||||
Msg( "%5i total\n", GI->max_edicts );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -937,7 +926,6 @@ void SV_InitHostCommands( void )
|
|||
Cmd_AddCommand( "map_background", SV_MapBackground_f, "set background map" );
|
||||
Cmd_AddCommand( "load", SV_Load_f, "load a saved game file" );
|
||||
Cmd_AddCommand( "loadquick", SV_QuickLoad_f, "load a quick-saved game file" );
|
||||
Cmd_AddCommand( "killsave", SV_DeleteSave_f, "delete a saved game file and saveshot" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -961,17 +949,18 @@ void SV_InitOperatorCommands( void )
|
|||
Cmd_AddCommand( "entpatch", SV_EntPatch_f, "write entity patch to allow external editing" );
|
||||
Cmd_AddCommand( "edict_usage", SV_EdictUsage_f, "show info about edicts usage" );
|
||||
Cmd_AddCommand( "entity_info", SV_EntityInfo_f, "show more info about edicts" );
|
||||
Cmd_AddCommand( "shutdownserver", SV_KillServer_f, "shutdown current server" );
|
||||
|
||||
if( host.type == HOST_NORMAL )
|
||||
{
|
||||
Cmd_AddCommand( "save", SV_Save_f, "save the game to a file" );
|
||||
Cmd_AddCommand( "savequick", SV_QuickSave_f, "save the game to the quicksave" );
|
||||
Cmd_AddCommand( "autosave", SV_AutoSave_f, "save the game to 'autosave' file" );
|
||||
Cmd_AddCommand( "killsave", SV_DeleteSave_f, "delete a saved game file and saveshot" );
|
||||
}
|
||||
else if( host.type == HOST_DEDICATED )
|
||||
{
|
||||
Cmd_AddCommand( "say", SV_ConSay_f, "send a chat message to everyone on the server" );
|
||||
Cmd_AddCommand( "killserver", SV_KillServer_f, "shutdown current server" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -998,6 +987,7 @@ void SV_KillOperatorCommands( void )
|
|||
Cmd_RemoveCommand( "entpatch" );
|
||||
Cmd_RemoveCommand( "edict_usage" );
|
||||
Cmd_RemoveCommand( "entity_info" );
|
||||
Cmd_RemoveCommand( "shutdownserver" );
|
||||
|
||||
if( host.type == HOST_NORMAL )
|
||||
{
|
||||
|
@ -1009,6 +999,5 @@ void SV_KillOperatorCommands( void )
|
|||
else if( host.type == HOST_DEDICATED )
|
||||
{
|
||||
Cmd_RemoveCommand( "say" );
|
||||
Cmd_RemoveCommand( "killserver" );
|
||||
}
|
||||
}
|
|
@ -177,8 +177,8 @@ void SV_ParseConsistencyResponse( sv_client_t *cl, sizebuf_t *msg )
|
|||
dropmessage[0] = 0;
|
||||
if( svgame.dllFuncs.pfnInconsistentFile( cl->edict, sv.resources[badresindex - 1].szFileName, dropmessage ))
|
||||
{
|
||||
if( Q_strlen( dropmessage ) > 0 )
|
||||
SV_ClientPrintf( cl, PRINT_HIGH, dropmessage );
|
||||
if( COM_CheckString( dropmessage ))
|
||||
SV_ClientPrintf( cl, dropmessage );
|
||||
SV_DropClient( cl );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -862,7 +862,7 @@ void SV_SendClientMessages( void )
|
|||
{
|
||||
MSG_Clear( &cl->netchan.message );
|
||||
MSG_Clear( &cl->datagram );
|
||||
SV_BroadcastPrintf( NULL, PRINT_HIGH, "%s overflowed\n", cl->name );
|
||||
SV_BroadcastPrintf( NULL, "%s overflowed\n", cl->name );
|
||||
MsgDev( D_WARN, "reliable overflow for %s\n", cl->name );
|
||||
SV_DropClient( cl );
|
||||
SetBits( cl->flags, FCL_SEND_NET_MESSAGE );
|
||||
|
|
|
@ -838,7 +838,7 @@ edict_t *SV_AllocEdict( void )
|
|||
edict_t *pEdict;
|
||||
int i;
|
||||
|
||||
for( i = svgame.globals->maxClients + 1; i < svgame.numEntities; i++ )
|
||||
for( i = svs.maxclients + 1; i < svgame.numEntities; i++ )
|
||||
{
|
||||
pEdict = EDICT_NUM( i );
|
||||
// the first couple seconds of server time can involve a lot of
|
||||
|
@ -850,8 +850,8 @@ edict_t *SV_AllocEdict( void )
|
|||
}
|
||||
}
|
||||
|
||||
if( i >= svgame.globals->maxEntities )
|
||||
Sys_Error( "ED_AllocEdict: no free edicts (max is %d)\n", svgame.globals->maxEntities );
|
||||
if( i >= GI->max_edicts )
|
||||
Sys_Error( "ED_AllocEdict: no free edicts (max is %d)\n", GI->max_edicts );
|
||||
|
||||
svgame.numEntities++;
|
||||
pEdict = EDICT_NUM( i );
|
||||
|
@ -1389,15 +1389,15 @@ int SV_CheckClientPVS( int check, qboolean bMergePVS )
|
|||
edict_t *ent = NULL;
|
||||
|
||||
// cycle to the next one
|
||||
check = bound( 1, check, svgame.globals->maxClients );
|
||||
check = bound( 1, check, svs.maxclients );
|
||||
|
||||
if( check == svgame.globals->maxClients )
|
||||
if( check == svs.maxclients )
|
||||
i = 1; // reset cycle
|
||||
else i = check + 1;
|
||||
|
||||
for( ;; i++ )
|
||||
{
|
||||
if( i == ( svgame.globals->maxClients + 1 ))
|
||||
if( i == ( svs.maxclients + 1 ))
|
||||
i = 1;
|
||||
|
||||
ent = EDICT_NUM( i );
|
||||
|
@ -1580,7 +1580,7 @@ void pfnRemoveEntity( edict_t* e )
|
|||
}
|
||||
|
||||
// never free client or world entity
|
||||
if( NUM_FOR_EDICT( e ) < ( svgame.globals->maxClients + 1 ))
|
||||
if( NUM_FOR_EDICT( e ) < ( svs.maxclients + 1 ))
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_RemoveEntity: can't delete %s\n", (e == EDICT_NUM( 0 )) ? "world" : "client" );
|
||||
return;
|
||||
|
@ -3243,10 +3243,8 @@ void pfnClientPrintf( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg )
|
|||
switch( ptype )
|
||||
{
|
||||
case print_console:
|
||||
SV_ClientPrintf( client, PRINT_HIGH, "%s", szMsg );
|
||||
break;
|
||||
case print_chat:
|
||||
SV_ClientPrintf( client, PRINT_CHAT, "%s", szMsg );
|
||||
SV_ClientPrintf( client, "%s", szMsg );
|
||||
break;
|
||||
case print_center:
|
||||
MSG_BeginServerCmd( &client->netchan.message, svc_centerprint );
|
||||
|
@ -3263,9 +3261,7 @@ pfnServerPrint
|
|||
*/
|
||||
void pfnServerPrint( const char *szMsg )
|
||||
{
|
||||
// while loading in-progress we can sending message only for local client
|
||||
if( sv.state != ss_active ) MsgDev( D_INFO, "%s", szMsg );
|
||||
else SV_BroadcastPrintf( NULL, PRINT_HIGH, "%s", szMsg );
|
||||
SV_BroadcastPrintf( NULL, "%s", szMsg );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3489,8 +3485,6 @@ void pfnRunPlayerMove( edict_t *pClient, const float *v_angle, float fmove, floa
|
|||
usercmd_t cmd;
|
||||
uint seed;
|
||||
|
||||
if( sv.paused ) return;
|
||||
|
||||
if(( cl = SV_ClientFromEdict( pClient, true )) == NULL )
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_ClientThink: fakeclient is not spawned!\n" );
|
||||
|
@ -4926,10 +4920,10 @@ qboolean SV_LoadProgs( const char *name )
|
|||
|
||||
svgame.globals->maxEntities = GI->max_edicts;
|
||||
svgame.globals->maxClients = svs.maxclients;
|
||||
svgame.edicts = Mem_Alloc( svgame.mempool, sizeof( edict_t ) * svgame.globals->maxEntities );
|
||||
svgame.numEntities = svgame.globals->maxClients + 1; // clients + world
|
||||
svgame.edicts = Mem_Alloc( svgame.mempool, sizeof( edict_t ) * GI->max_edicts );
|
||||
svgame.numEntities = svs.maxclients + 1; // clients + world
|
||||
|
||||
for( i = 0, e = svgame.edicts; i < svgame.globals->maxEntities; i++, e++ )
|
||||
for( i = 0, e = svgame.edicts; i < GI->max_edicts; i++, e++ )
|
||||
e->free = true; // mark all edicts as freed
|
||||
|
||||
// clear user messages
|
||||
|
|
|
@ -477,12 +477,11 @@ void SV_FreeOldEntities( void )
|
|||
int i;
|
||||
|
||||
// at end of frame kill all entities which supposed to it
|
||||
for( i = svgame.globals->maxClients + 1; i < svgame.numEntities; i++ )
|
||||
for( i = svs.maxclients + 1; i < svgame.numEntities; i++ )
|
||||
{
|
||||
ent = EDICT_NUM( i );
|
||||
if( ent->free ) continue;
|
||||
|
||||
if( ent->v.flags & FL_KILLME )
|
||||
if( !ent->free && FBitSet( ent->v.flags, FL_KILLME ))
|
||||
SV_FreeEdict( ent );
|
||||
}
|
||||
|
||||
|
@ -497,39 +496,48 @@ SV_ActivateServer
|
|||
activate server on changed map, run physics
|
||||
================
|
||||
*/
|
||||
void SV_ActivateServer( void )
|
||||
void SV_ActivateServer( int runPhysics )
|
||||
{
|
||||
int i, numFrames;
|
||||
int i, numFrames;
|
||||
byte msg_buf[MAX_INIT_MSG];
|
||||
sizebuf_t msg;
|
||||
sv_client_t *cl;
|
||||
|
||||
if( !svs.initialized )
|
||||
return;
|
||||
|
||||
// Activate the DLL server code
|
||||
svgame.dllFuncs.pfnServerActivate( svgame.edicts, svgame.numEntities, svgame.globals->maxClients );
|
||||
MSG_Init( &msg, "NewServer", msg_buf, sizeof( msg_buf ));
|
||||
|
||||
if( sv.loadgame || svgame.globals->changelevel )
|
||||
{
|
||||
sv.frametime = bound( 0.001, sv_changetime.value, 0.1 );
|
||||
numFrames = 1;
|
||||
}
|
||||
else if( svs.maxclients <= 1 )
|
||||
// always clearing newunit variable
|
||||
Cvar_SetValue( "sv_newunit", 0 );
|
||||
|
||||
// relese all intermediate entities
|
||||
SV_FreeOldEntities ();
|
||||
|
||||
// Activate the DLL server code
|
||||
svgame.globals->time = sv.time;
|
||||
svgame.dllFuncs.pfnServerActivate( svgame.edicts, svgame.numEntities, svs.maxclients );
|
||||
|
||||
// parse user-specified resources
|
||||
SV_CreateGenericResources();
|
||||
|
||||
sv.state = ss_active;
|
||||
|
||||
if( runPhysics )
|
||||
{
|
||||
sv.frametime = bound( 0.1, sv_spawntime.value, 0.8 );
|
||||
numFrames = 2;
|
||||
numFrames = (svs.maxclients <= 1) ? 2 : 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
sv.frametime = 0.1f;
|
||||
numFrames = 8;
|
||||
sv.frametime = bound( 0.001, sv_changetime.value, 0.1 );
|
||||
numFrames = 0;
|
||||
}
|
||||
|
||||
// run some frames to allow everything to settle
|
||||
for( i = 0; i < numFrames; i++ )
|
||||
SV_Physics();
|
||||
|
||||
// parse user-specified resources
|
||||
SV_CreateGenericResources();
|
||||
|
||||
// create a baseline for more efficient communications
|
||||
SV_CreateBaseline();
|
||||
|
||||
|
@ -540,18 +548,26 @@ void SV_ActivateServer( void )
|
|||
sv.num_consistency = SV_TransferConsistencyInfo();
|
||||
|
||||
// send serverinfo to all connected clients
|
||||
for( i = 0; i < svs.maxclients; i++ )
|
||||
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ )
|
||||
{
|
||||
if( svs.clients[i].state >= cs_connected )
|
||||
{
|
||||
Netchan_Clear( &svs.clients[i].netchan );
|
||||
svs.clients[i].delta_sequence = -1;
|
||||
}
|
||||
if( cl->state < cs_connected )
|
||||
continue;
|
||||
|
||||
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
|
||||
memset( &svgame.oldmovevars, 0, sizeof( movevars_t ));
|
||||
svgame.globals->changelevel = false; // changelevel ends here
|
||||
svgame.globals->changelevel = false;
|
||||
|
||||
// setup hostflags
|
||||
sv.hostflags = 0;
|
||||
|
@ -559,9 +575,9 @@ void SV_ActivateServer( void )
|
|||
HPAK_FlushHostQueue();
|
||||
|
||||
// tell what kind of server has been started.
|
||||
if( svgame.globals->maxClients > 1 )
|
||||
if( svs.maxclients > 1 )
|
||||
{
|
||||
MsgDev( D_INFO, "%i player server started\n", svgame.globals->maxClients );
|
||||
MsgDev( D_INFO, "%i player server started\n", svs.maxclients );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -574,11 +590,7 @@ void SV_ActivateServer( void )
|
|||
if( host.type == HOST_DEDICATED )
|
||||
Mod_FreeUnused ();
|
||||
|
||||
sv.state = ss_active;
|
||||
host.movevars_changed = true;
|
||||
sv.changelevel = false;
|
||||
sv.paused = false;
|
||||
|
||||
Host_SetServerState( sv.state );
|
||||
|
||||
MsgDev( D_INFO, "level loaded at %.2f sec\n", Sys_DoubleTime() - svs.timestart );
|
||||
|
@ -629,65 +641,12 @@ void SV_DeactivateServer( void )
|
|||
|
||||
svgame.globals->maxEntities = GI->max_edicts;
|
||||
svgame.globals->maxClients = svs.maxclients;
|
||||
svgame.numEntities = svgame.globals->maxClients + 1; // clients + world
|
||||
svgame.numEntities = svs.maxclients + 1; // clients + world
|
||||
svgame.globals->startspot = 0;
|
||||
svgame.globals->mapname = 0;
|
||||
|
||||
// clear states
|
||||
sv.changelevel = false;
|
||||
sv.background = false;
|
||||
sv.loadgame = false;
|
||||
sv.state = ss_dead;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_LevelInit
|
||||
|
||||
Spawn all entities
|
||||
================
|
||||
*/
|
||||
void SV_LevelInit( const char *pMapName, char const *pOldLevel, char const *pLandmarkName, qboolean loadGame )
|
||||
{
|
||||
if( !svs.initialized )
|
||||
return;
|
||||
|
||||
if( loadGame )
|
||||
{
|
||||
if( !SV_LoadGameState( pMapName, 1 ))
|
||||
{
|
||||
SV_SpawnEntities( pMapName, SV_EntityScript( ));
|
||||
}
|
||||
|
||||
if( pOldLevel )
|
||||
{
|
||||
SV_LoadAdjacentEnts( pOldLevel, pLandmarkName );
|
||||
}
|
||||
|
||||
if( sv_newunit.value )
|
||||
{
|
||||
SV_ClearSaveDir();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
svgame.dllFuncs.pfnResetGlobalState();
|
||||
SV_SpawnEntities( pMapName, SV_EntityScript( ));
|
||||
svgame.globals->frametime = 0.0f;
|
||||
|
||||
if( sv_newunit.value )
|
||||
{
|
||||
SV_ClearSaveDir();
|
||||
}
|
||||
}
|
||||
|
||||
// always clearing newunit variable
|
||||
Cvar_SetValue( "sv_newunit", 0 );
|
||||
|
||||
// relese all intermediate entities
|
||||
SV_FreeOldEntities ();
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SV_InitGame
|
||||
|
@ -695,34 +654,100 @@ SV_InitGame
|
|||
A brand new game has been started
|
||||
==============
|
||||
*/
|
||||
void SV_InitGame( void )
|
||||
qboolean SV_InitGame( void )
|
||||
{
|
||||
edict_t *ent;
|
||||
int i, load = sv.loadgame;
|
||||
|
||||
if( svs.initialized )
|
||||
return true; // already initialized ?
|
||||
|
||||
// first initialize?
|
||||
if( !SV_LoadProgs( GI->game_dll ))
|
||||
{
|
||||
// cause any connected clients to reconnect
|
||||
Q_strncpy( host.finalmsg, "Server restarted", MAX_STRING );
|
||||
SV_Shutdown( true );
|
||||
MsgDev( D_ERROR, "SV_InitGame: can't initialize %s\n", GI->game_dll );
|
||||
return false; // failed to loading server.dll
|
||||
}
|
||||
|
||||
// alloc baseline slots
|
||||
svs.baselines = Z_Malloc( sizeof( entity_state_t ) * GI->max_edicts );
|
||||
// client frames will be allocated in SV_ClientConnect
|
||||
svs.initialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SV_ShutdownGame
|
||||
|
||||
prepare to close server
|
||||
==============
|
||||
*/
|
||||
void SV_ShutdownGame( void )
|
||||
{
|
||||
if( !GameState->loadGame )
|
||||
SV_ClearGameState();
|
||||
|
||||
S_StopBackgroundTrack();
|
||||
|
||||
if( GameState->newGame )
|
||||
{
|
||||
Host_EndGame( false, DEFAULT_ENDGAME_MESSAGE );
|
||||
}
|
||||
else
|
||||
{
|
||||
// init game after host error
|
||||
if( !svgame.hInstance )
|
||||
{
|
||||
if( !SV_LoadProgs( GI->game_dll ))
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_InitGame: can't initialize %s\n", GI->game_dll );
|
||||
return; // can't loading
|
||||
}
|
||||
}
|
||||
S_StopAllSounds( true );
|
||||
SV_DeactivateServer();
|
||||
}
|
||||
}
|
||||
|
||||
// make sure the client is down
|
||||
CL_Drop();
|
||||
/*
|
||||
================
|
||||
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
|
||||
|
||||
determine the game type and prepare clients
|
||||
================
|
||||
*/
|
||||
void SV_SetupClients( void )
|
||||
{
|
||||
qboolean changed_maxclients = false;
|
||||
|
||||
// check if clients count was really changed
|
||||
if( svs.maxclients != (int)sv_maxclients->value )
|
||||
changed_maxclients = true;
|
||||
svs.maxclients = sv_maxclients->value; // copy the actual value from cvar
|
||||
|
||||
if( svs.maxclients == 1 )
|
||||
{
|
||||
if( deathmatch.value )
|
||||
{
|
||||
changed_maxclients = true;
|
||||
svs.maxclients = 8;
|
||||
}
|
||||
else if( coop.value )
|
||||
{
|
||||
changed_maxclients = true;
|
||||
svs.maxclients = 4;
|
||||
}
|
||||
}
|
||||
|
||||
svs.maxclients = sv_maxclients->value; // copy the actual value from cvar
|
||||
if( !changed_maxclients ) return; // nothing to change
|
||||
|
||||
// dedicated servers are can't be single player and are usually DM
|
||||
if( host.type == HOST_DEDICATED )
|
||||
|
@ -741,13 +766,10 @@ void SV_InitGame( void )
|
|||
SV_UPDATE_BACKUP = ( svs.maxclients == 1 ) ? SINGLEPLAYER_BACKUP : MULTIPLAYER_BACKUP;
|
||||
svgame.globals->maxClients = svs.maxclients;
|
||||
|
||||
svs.clients = Z_Malloc( sizeof( sv_client_t ) * svs.maxclients );
|
||||
svs.clients = Z_Realloc( svs.clients, sizeof( sv_client_t ) * svs.maxclients );
|
||||
svs.num_client_entities = svs.maxclients * SV_UPDATE_BACKUP * NUM_PACKET_ENTITIES;
|
||||
svs.packet_entities = Z_Malloc( sizeof( entity_state_t ) * svs.num_client_entities );
|
||||
svs.baselines = Z_Malloc( sizeof( entity_state_t ) * GI->max_edicts );
|
||||
if( !load ) MsgDev( D_INFO, "%s alloced by server packet entities\n", Q_memprint( sizeof( entity_state_t ) * svs.num_client_entities ));
|
||||
|
||||
// client frames will be allocated in SV_DirectConnect
|
||||
svs.packet_entities = Z_Realloc( svs.packet_entities, sizeof( entity_state_t ) * svs.num_client_entities );
|
||||
MsgDev( D_INFO, "%s alloced by server packet entities\n", Q_memprint( sizeof( entity_state_t ) * svs.num_client_entities ));
|
||||
|
||||
// init network stuff
|
||||
NET_Config(( svs.maxclients > 1 ));
|
||||
|
@ -755,24 +777,11 @@ void SV_InitGame( void )
|
|||
// copy gamemode into svgame.globals
|
||||
svgame.globals->deathmatch = deathmatch.value;
|
||||
svgame.globals->coop = coop.value;
|
||||
svgame.numEntities = svs.maxclients + 1; // clients + world
|
||||
|
||||
// heartbeats will always be sent to the id master
|
||||
svs.last_heartbeat = MAX_HEARTBEAT; // send immediately
|
||||
|
||||
// set client fields on player ents
|
||||
for( i = 0; i < svgame.globals->maxClients; i++ )
|
||||
{
|
||||
// setup all the clients
|
||||
ent = EDICT_NUM( i + 1 );
|
||||
svs.clients[i].edict = ent;
|
||||
SV_InitEdict( ent );
|
||||
}
|
||||
|
||||
// get actual movevars
|
||||
SV_UpdateMovevars( true );
|
||||
|
||||
svgame.numEntities = svgame.globals->maxClients + 1; // clients + world
|
||||
svs.initialized = true;
|
||||
ClearBits( sv_maxclients->flags, FCVAR_CHANGED );
|
||||
ClearBits( deathmatch.flags, FCVAR_CHANGED );
|
||||
ClearBits( coop.flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -786,28 +795,18 @@ clients along with it.
|
|||
qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean background )
|
||||
{
|
||||
int i, current_skill;
|
||||
qboolean loadgame, paused;
|
||||
qboolean changelevel;
|
||||
edict_t *ent;
|
||||
|
||||
// save state
|
||||
loadgame = sv.loadgame;
|
||||
changelevel = sv.changelevel;
|
||||
paused = sv.paused;
|
||||
|
||||
if( sv.state == ss_dead )
|
||||
SV_InitGame(); // the game is just starting
|
||||
|
||||
NET_Config(( svs.maxclients > 1 )); // init network stuff
|
||||
ClearBits( sv_maxclients->flags, FCVAR_CHANGED );
|
||||
|
||||
if( !svs.initialized )
|
||||
if( !SV_InitGame( ))
|
||||
return false;
|
||||
|
||||
Log_Open();
|
||||
Log_Printf( "Loading map \"%s\"\n", mapname );
|
||||
Log_PrintServerVars();
|
||||
|
||||
svgame.globals->changelevel = false; // will be restored later if needed
|
||||
SV_SetupClients();
|
||||
SV_AllocClientFrames();
|
||||
|
||||
svs.timestart = Sys_DoubleTime();
|
||||
svs.spawncount++; // any partially connected client will be restarted
|
||||
|
||||
|
@ -824,13 +823,8 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba
|
|||
Host_SetServerState( sv.state );
|
||||
memset( &sv, 0, sizeof( sv )); // wipe the entire per-level structure
|
||||
|
||||
// restore state
|
||||
sv.paused = paused;
|
||||
sv.loadgame = loadgame;
|
||||
sv.time = svgame.globals->time = 1.0f; // server spawn time it's always 1.0 second
|
||||
sv.background = background;
|
||||
sv.changelevel = changelevel;
|
||||
sv.time = 1.0f; // server spawn time it's always 1.0 second
|
||||
svgame.globals->time = sv.time;
|
||||
|
||||
// initialize buffers
|
||||
MSG_Init( &sv.signon, "Signon", sv.signon_buf, sizeof( sv.signon_buf ));
|
||||
|
@ -839,19 +833,10 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba
|
|||
MSG_Init( &sv.reliable_datagram, "Reliable Datagram", sv.reliable_datagram_buf, sizeof( sv.reliable_datagram_buf ));
|
||||
MSG_Init( &sv.spec_datagram, "Spectator Datagram", sv.spectator_buf, sizeof( sv.spectator_buf ));
|
||||
|
||||
// leave slots at start for clients only
|
||||
for( i = 0; i < svs.maxclients; i++ )
|
||||
{
|
||||
// needs to reconnect
|
||||
if( svs.clients[i].state > cs_connected )
|
||||
svs.clients[i].state = cs_connected;
|
||||
}
|
||||
|
||||
// make cvars consistant
|
||||
if( coop.value ) Cvar_SetValue( "deathmatch", 0 );
|
||||
current_skill = Q_rint( skill.value );
|
||||
current_skill = bound( 0, current_skill, 3 );
|
||||
|
||||
Cvar_SetValue( "skill", (float)current_skill );
|
||||
|
||||
if( sv.background )
|
||||
|
@ -885,11 +870,29 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba
|
|||
SetBits( sv.model_precache_flags[i+1], RES_FATALIFMISSING );
|
||||
}
|
||||
|
||||
// leave slots at start for clients only
|
||||
for( i = 0; i < svs.maxclients; i++ )
|
||||
{
|
||||
// needs to reconnect
|
||||
if( svs.clients[i].state > cs_connected )
|
||||
svs.clients[i].state = cs_connected;
|
||||
|
||||
ent = EDICT_NUM( i + 1 );
|
||||
svs.clients[i].edict = ent;
|
||||
SV_InitEdict( ent );
|
||||
}
|
||||
|
||||
// heartbeats will always be sent to the id master
|
||||
svs.last_heartbeat = MAX_HEARTBEAT; // send immediately
|
||||
|
||||
// precache and static commands can be issued during map initialization
|
||||
sv.state = ss_loading;
|
||||
|
||||
Host_SetServerState( sv.state );
|
||||
|
||||
// get actual movevars
|
||||
SV_UpdateMovevars( true );
|
||||
|
||||
// clear physics interaction links
|
||||
SV_ClearWorld();
|
||||
|
||||
|
@ -897,6 +900,11 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba
|
|||
}
|
||||
|
||||
qboolean SV_Active( void )
|
||||
{
|
||||
return (sv.state != ss_dead);
|
||||
}
|
||||
|
||||
qboolean SV_Initialized( void )
|
||||
{
|
||||
return svs.initialized;
|
||||
}
|
||||
|
@ -920,4 +928,50 @@ void SV_FreeGameProgs( void )
|
|||
|
||||
// unload progs (free cvars and commands)
|
||||
SV_UnloadProgs();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_ExecLoadLevel
|
||||
|
||||
State machine exec new map
|
||||
================
|
||||
*/
|
||||
void SV_ExecLoadLevel( void )
|
||||
{
|
||||
if( SV_SpawnServer( GameState->levelName, NULL, GameState->backgroundMap ))
|
||||
{
|
||||
SV_SpawnEntities( GameState->levelName, SV_EntityScript( ));
|
||||
SV_ActivateServer( true );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_ExecLoadGame
|
||||
|
||||
State machine exec load saved game
|
||||
================
|
||||
*/
|
||||
void SV_ExecLoadGame( void )
|
||||
{
|
||||
if( SV_SpawnServer( GameState->levelName, NULL, false ))
|
||||
{
|
||||
if( !SV_LoadGameState( GameState->levelName, false ))
|
||||
SV_SpawnEntities( GameState->levelName, SV_EntityScript( ));
|
||||
sv.loadgame = sv.paused = true; // pause until all clients connect
|
||||
SV_ActivateServer( false );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_ExecChangeLevel
|
||||
|
||||
State machine exec changelevel path
|
||||
================
|
||||
*/
|
||||
void SV_ExecChangeLevel( void )
|
||||
{
|
||||
SV_ChangeLevel( GameState->loadGame, GameState->levelName, GameState->landmarkName );
|
||||
}
|
|
@ -166,11 +166,11 @@ void SV_ServerLog_f( sv_client_t *cl )
|
|||
|
||||
if( Cmd_Argc() != 2 )
|
||||
{
|
||||
SV_ClientPrintf( cl, PRINT_HIGH, "usage: log < on|off >\n" );
|
||||
SV_ClientPrintf( cl, "usage: log < on|off >\n" );
|
||||
|
||||
if( svs.log.active )
|
||||
SV_ClientPrintf( cl, PRINT_HIGH, "currently logging\n" );
|
||||
else SV_ClientPrintf( cl, PRINT_HIGH, "not currently logging\n" );
|
||||
SV_ClientPrintf( cl, "currently logging\n" );
|
||||
else SV_ClientPrintf( cl, "not currently logging\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -186,6 +186,6 @@ void SV_ServerLog_f( sv_client_t *cl )
|
|||
}
|
||||
else
|
||||
{
|
||||
SV_ClientPrintf( cl, PRINT_HIGH, "log: unknown parameter %s\n", Cmd_Argv( 1 ));
|
||||
SV_ClientPrintf( cl, "log: unknown parameter %s\n", Cmd_Argv( 1 ));
|
||||
}
|
||||
}
|
|
@ -59,8 +59,8 @@ CVAR_DEFINE_AUTO( mapcyclefile, "mapcycle.txt", 0, "name of multiplayer map cycl
|
|||
CVAR_DEFINE_AUTO( motdfile, "motd.txt", 0, "name of 'message of the day' file" );
|
||||
CVAR_DEFINE_AUTO( logsdir, "logs", 0, "place to store multiplayer logs" );
|
||||
CVAR_DEFINE_AUTO( bannedcfgfile, "banned.cfg", 0, "name of list of banned users" );
|
||||
CVAR_DEFINE_AUTO( deathmatch, "0", 0, "deathmatch mode in multiplayer game" );
|
||||
CVAR_DEFINE_AUTO( coop, "0", 0, "cooperative mode in multiplayer game" );
|
||||
CVAR_DEFINE_AUTO( deathmatch, "0", FCVAR_LATCH, "deathmatch mode in multiplayer game" );
|
||||
CVAR_DEFINE_AUTO( coop, "0", FCVAR_LATCH, "cooperative mode in multiplayer game" );
|
||||
CVAR_DEFINE_AUTO( teamplay, "0", 0, "team mode in multiplayer game" );
|
||||
CVAR_DEFINE_AUTO( skill, "1", 0, "skill level in singleplayer game" );
|
||||
CVAR_DEFINE_AUTO( temp1, "0", 0, "temporary cvar that used by some mods" );
|
||||
|
@ -418,7 +418,7 @@ void SV_CheckTimeouts( void )
|
|||
{
|
||||
if( !NET_IsLocalAddress( cl->netchan.remote_address ))
|
||||
{
|
||||
SV_BroadcastPrintf( NULL, PRINT_HIGH, "%s timed out\n", cl->name );
|
||||
SV_BroadcastPrintf( NULL, "%s timed out\n", cl->name );
|
||||
SV_DropClient( cl );
|
||||
cl->state = cs_free; // don't bother with zombie state
|
||||
}
|
||||
|
@ -825,14 +825,13 @@ void SV_FinalMessage( char *message, qboolean reconnect )
|
|||
|
||||
MSG_Init( &msg, "FinalMessage", msg_buf, sizeof( msg_buf ));
|
||||
MSG_BeginServerCmd( &msg, svc_print );
|
||||
MSG_WriteByte( &msg, PRINT_HIGH );
|
||||
MSG_WriteString( &msg, va( "%s\n", message ));
|
||||
|
||||
if( reconnect )
|
||||
{
|
||||
MSG_BeginServerCmd( &msg, svc_changing );
|
||||
|
||||
if( sv.loadgame || svs.maxclients > 1 || sv.changelevel )
|
||||
if( svs.maxclients > 1 || sv.changelevel )
|
||||
MSG_WriteOneBit( &msg, 1 ); // changelevel
|
||||
else MSG_WriteOneBit( &msg, 0 );
|
||||
}
|
||||
|
@ -852,6 +851,29 @@ void SV_FinalMessage( char *message, qboolean reconnect )
|
|||
Netchan_Transmit( &cl->netchan, MSG_GetNumBytesWritten( &msg ), MSG_GetData( &msg ));
|
||||
}
|
||||
|
||||
void SV_FreeClients( void )
|
||||
{
|
||||
if( svs.maxclients != 0 )
|
||||
{
|
||||
// free server static data
|
||||
if( svs.clients )
|
||||
{
|
||||
Z_Free( svs.clients );
|
||||
svs.clients = NULL;
|
||||
}
|
||||
|
||||
if( svs.packet_entities )
|
||||
{
|
||||
Z_Free( svs.packet_entities );
|
||||
svs.packet_entities = NULL;
|
||||
svs.num_client_entities = 0;
|
||||
svs.next_client_entities = 0;
|
||||
}
|
||||
|
||||
svs.maxclients = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_Shutdown
|
||||
|
@ -863,7 +885,7 @@ before Sys_Quit or Sys_Error
|
|||
void SV_Shutdown( qboolean reconnect )
|
||||
{
|
||||
// already freed
|
||||
if( !SV_Active( )) return;
|
||||
if( !SV_Initialized( )) return;
|
||||
|
||||
// rcon will be disconnected
|
||||
SV_EndRedirect();
|
||||
|
@ -882,31 +904,18 @@ void SV_Shutdown( qboolean reconnect )
|
|||
|
||||
// free current level
|
||||
memset( &sv, 0, sizeof( sv ));
|
||||
Host_SetServerState( sv.state );
|
||||
Host_SetServerState( ss_dead );
|
||||
|
||||
SV_FreeClients();
|
||||
|
||||
Log_Printf( "Server shutdown\n" );
|
||||
Log_Close();
|
||||
|
||||
// free server static data
|
||||
if( svs.clients )
|
||||
{
|
||||
Z_Free( svs.clients );
|
||||
svs.clients = NULL;
|
||||
}
|
||||
|
||||
if( svs.baselines )
|
||||
{
|
||||
Z_Free( svs.baselines );
|
||||
svs.baselines = NULL;
|
||||
}
|
||||
|
||||
if( svs.packet_entities )
|
||||
{
|
||||
Z_Free( svs.packet_entities );
|
||||
svs.packet_entities = NULL;
|
||||
svs.num_client_entities = 0;
|
||||
svs.next_client_entities = 0;
|
||||
}
|
||||
|
||||
svs.initialized = false;
|
||||
}
|
|
@ -80,7 +80,7 @@ void SV_CheckAllEnts( void )
|
|||
nextcheck = Sys_DoubleTime() + 5.0;
|
||||
|
||||
// check edicts errors
|
||||
for( i = svgame.globals->maxClients + 1; i < svgame.numEntities; i++ )
|
||||
for( i = svs.maxclients + 1; i < svgame.numEntities; i++ )
|
||||
{
|
||||
e = EDICT_NUM( i );
|
||||
|
||||
|
@ -896,7 +896,7 @@ static edict_t *SV_PushMove( edict_t *pusher, float movetime )
|
|||
sv_pushed_t *p, *pushed_p;
|
||||
edict_t *check;
|
||||
|
||||
if( svgame.globals->changelevel || VectorIsNull( pusher->v.velocity ))
|
||||
if( VectorIsNull( pusher->v.velocity ))
|
||||
{
|
||||
pusher->v.ltime += movetime;
|
||||
return NULL;
|
||||
|
@ -1014,7 +1014,7 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
|||
vec3_t org, org2, temp;
|
||||
edict_t *check;
|
||||
|
||||
if( svgame.globals->changelevel || VectorIsNull( pusher->v.avelocity ))
|
||||
if( VectorIsNull( pusher->v.avelocity ))
|
||||
{
|
||||
pusher->v.ltime += movetime;
|
||||
return NULL;
|
||||
|
@ -1800,7 +1800,7 @@ void SV_Physics( void )
|
|||
if( !SV_IsValidEdict( ent ))
|
||||
continue;
|
||||
|
||||
if( i > 0 && i <= svgame.globals->maxClients )
|
||||
if( i > 0 && i <= svs.maxclients )
|
||||
continue;
|
||||
|
||||
SV_Physics_Entity( ent );
|
||||
|
|
|
@ -32,6 +32,9 @@ 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;
|
||||
|
||||
|
|
|
@ -1060,7 +1060,7 @@ SV_SaveClientState
|
|||
write out the list of premanent decals for this level
|
||||
=============
|
||||
*/
|
||||
void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level )
|
||||
void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level, int changelevel )
|
||||
{
|
||||
string name;
|
||||
file_t *pFile;
|
||||
|
@ -1094,7 +1094,7 @@ void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level )
|
|||
|
||||
// g-cont. add space for studiodecals if present
|
||||
decalList = (decallist_t *)Z_Malloc( sizeof( decallist_t ) * MAX_RENDER_DECALS * 2 );
|
||||
decalCount = R_CreateDecalList( decalList, svgame.globals->changelevel );
|
||||
decalCount = R_CreateDecalList( decalList );
|
||||
|
||||
// DECALS SECTION
|
||||
sections.offsets[LUMP_DECALS_OFFSET] = FS_Tell( pFile );
|
||||
|
@ -1175,7 +1175,7 @@ void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level )
|
|||
}
|
||||
|
||||
// DYNAMIC SOUNDS SECTION (don't go across transition)
|
||||
if( !svgame.globals->changelevel && ( soundCount = S_GetCurrentDynamicSounds( soundInfo, MAX_CHANNELS )) != 0 )
|
||||
if( !changelevel && ( soundCount = S_GetCurrentDynamicSounds( soundInfo, MAX_CHANNELS )) != 0 )
|
||||
{
|
||||
sections.offsets[LUMP_SOUNDS_OFFSET] = FS_Tell( pFile );
|
||||
FS_Write( pFile, &soundCount, sizeof( int ));
|
||||
|
@ -1205,7 +1205,7 @@ void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level )
|
|||
}
|
||||
|
||||
// BACKGROUND MUSIC SECTION (don't go across transition)
|
||||
if( !svgame.globals->changelevel && S_StreamGetCurrentState( curtrack, looptrack, &position ))
|
||||
if( !changelevel && S_StreamGetCurrentState( curtrack, looptrack, &position ))
|
||||
{
|
||||
byte nameSize;
|
||||
|
||||
|
@ -1440,7 +1440,7 @@ SV_SaveGameState
|
|||
save current game state
|
||||
=============
|
||||
*/
|
||||
SAVERESTOREDATA *SV_SaveGameState( void )
|
||||
SAVERESTOREDATA *SV_SaveGameState( int changelevel )
|
||||
{
|
||||
SaveFileSectionsInfo_t sectionsInfo;
|
||||
SaveFileSections_t sections;
|
||||
|
@ -1528,12 +1528,12 @@ SAVERESTOREDATA *SV_SaveGameState( void )
|
|||
|
||||
SV_EntityPatchWrite( pSaveData, sv.name );
|
||||
|
||||
SV_SaveClientState( pSaveData, sv.name );
|
||||
SV_SaveClientState( pSaveData, sv.name, changelevel );
|
||||
|
||||
return pSaveData;
|
||||
}
|
||||
|
||||
int SV_LoadGameState( char const *level, qboolean createPlayers )
|
||||
int SV_LoadGameState( char const *level, qboolean changelevel )
|
||||
{
|
||||
SAVE_HEADER header;
|
||||
SAVERESTOREDATA *pSaveData;
|
||||
|
@ -1578,7 +1578,7 @@ int SV_LoadGameState( char const *level, qboolean createPlayers )
|
|||
// create entity list
|
||||
if( svgame.physFuncs.pfnCreateEntitiesInRestoreList != NULL )
|
||||
{
|
||||
svgame.physFuncs.pfnCreateEntitiesInRestoreList( pSaveData, createPlayers );
|
||||
svgame.physFuncs.pfnCreateEntitiesInRestoreList( pSaveData );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1586,7 +1586,7 @@ int SV_LoadGameState( char const *level, qboolean createPlayers )
|
|||
{
|
||||
pEntInfo = &pSaveData->pTable[i];
|
||||
|
||||
if( pEntInfo->classname != 0 && pEntInfo->size && !( pEntInfo->flags & FENTTABLE_REMOVED ))
|
||||
if( pEntInfo->classname != 0 && pEntInfo->size && !FBitSet( pEntInfo->flags, FENTTABLE_REMOVED ))
|
||||
{
|
||||
if( pEntInfo->id == 0 ) // worldspawn
|
||||
{
|
||||
|
@ -1597,11 +1597,11 @@ int SV_LoadGameState( char const *level, qboolean createPlayers )
|
|||
SV_InitEdict( pent );
|
||||
pent = SV_CreateNamedEntity( pent, pEntInfo->classname );
|
||||
}
|
||||
else if(( pEntInfo->id > 0 ) && ( pEntInfo->id < svgame.globals->maxClients + 1 ))
|
||||
else if(( pEntInfo->id > 0 ) && ( pEntInfo->id < svs.maxclients + 1 ))
|
||||
{
|
||||
edict_t *ed;
|
||||
|
||||
if(!( pEntInfo->flags & FENTTABLE_PLAYER ))
|
||||
if( !FBitSet( pEntInfo->flags, FENTTABLE_PLAYER ))
|
||||
{
|
||||
MsgDev( D_WARN, "ENTITY IS NOT A PLAYER: %d\n", i );
|
||||
Assert( 0 );
|
||||
|
@ -1609,9 +1609,9 @@ int SV_LoadGameState( char const *level, qboolean createPlayers )
|
|||
|
||||
ed = EDICT_NUM( pEntInfo->id );
|
||||
|
||||
if( ed && createPlayers )
|
||||
if( ed != NULL )
|
||||
{
|
||||
Assert( ed->free == false );
|
||||
ASSERT( ed->free == false );
|
||||
// create the player
|
||||
pent = SV_CreateNamedEntity( ed, pEntInfo->classname );
|
||||
}
|
||||
|
@ -1653,7 +1653,7 @@ int SV_LoadGameState( char const *level, qboolean createPlayers )
|
|||
pent = pSaveData->pTable[bound( 0, (word)header.viewentity, pSaveData->tableCount )].pent;
|
||||
|
||||
// don't go camera across the levels
|
||||
if( SV_IsValidEdict( pent ) && !svgame.globals->changelevel )
|
||||
if( SV_IsValidEdict( pent ) && !changelevel )
|
||||
sv.viewentity = NUM_FOR_EDICT( pent );
|
||||
else sv.viewentity = 0;
|
||||
|
||||
|
@ -1670,6 +1670,21 @@ int SV_LoadGameState( char const *level, qboolean createPlayers )
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_ClearGameState
|
||||
|
||||
clear current game state
|
||||
=============
|
||||
*/
|
||||
void SV_ClearGameState( void )
|
||||
{
|
||||
SV_ClearSaveDir();
|
||||
|
||||
if( svgame.dllFuncs.pfnResetGlobalState != NULL )
|
||||
svgame.dllFuncs.pfnResetGlobalState();
|
||||
}
|
||||
|
||||
// ripped out from the hl.dll
|
||||
edict_t *SV_FindGlobalEntity( string_t classname, string_t globalname )
|
||||
{
|
||||
|
@ -1715,7 +1730,7 @@ int SV_CreateEntityTransitionList( SAVERESTOREDATA *pSaveData, int levelMask )
|
|||
active = (pEntInfo->flags & levelMask) ? 1 : 0;
|
||||
|
||||
// spawn players
|
||||
if(( pEntInfo->id > 0 ) && ( pEntInfo->id < svgame.globals->maxClients + 1 ))
|
||||
if(( pEntInfo->id > 0 ) && ( pEntInfo->id < svs.maxclients + 1 ))
|
||||
{
|
||||
edict_t *ed = EDICT_NUM( pEntInfo->id );
|
||||
|
||||
|
@ -1942,11 +1957,9 @@ void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char
|
|||
svgame.globals->changelevel = true;
|
||||
|
||||
// save the current level's state
|
||||
pSaveData = SV_SaveGameState();
|
||||
sv.loadgame = true;
|
||||
pSaveData = SV_SaveGameState( true );
|
||||
}
|
||||
|
||||
SV_InactivateClients ();
|
||||
SV_DeactivateServer ();
|
||||
|
||||
if( !SV_SpawnServer( level, startspot, false ))
|
||||
|
@ -1954,20 +1967,24 @@ void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char
|
|||
|
||||
if( loadfromsavedgame )
|
||||
{
|
||||
// Finish saving gamestate
|
||||
// finish saving gamestate
|
||||
SV_SaveFinish( pSaveData );
|
||||
|
||||
svgame.globals->changelevel = true;
|
||||
SV_LevelInit( level, oldlevel, startspot, true );
|
||||
sv.paused = true; // pause until all clients connect
|
||||
sv.loadgame = true;
|
||||
if( !SV_LoadGameState( level, true ))
|
||||
SV_SpawnEntities( level, SV_EntityScript( ));
|
||||
SV_LoadAdjacentEnts( oldlevel, startspot );
|
||||
sv.loadgame = sv.paused = true; // pause until all clients connect
|
||||
|
||||
if( sv_newunit.value )
|
||||
SV_ClearSaveDir();
|
||||
SV_ActivateServer( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
SV_LevelInit( level, NULL, NULL, false );
|
||||
// classic quake changelevel
|
||||
SV_SpawnEntities( level, SV_EntityScript( ));
|
||||
SV_ActivateServer( true );
|
||||
}
|
||||
|
||||
SV_ActivateServer ();
|
||||
}
|
||||
|
||||
int SV_SaveGameSlot( const char *pSaveName, const char *pSaveComment )
|
||||
|
@ -1979,7 +1996,7 @@ int SV_SaveGameSlot( const char *pSaveName, const char *pSaveComment )
|
|||
int i, tag, tokenSize;
|
||||
file_t *pFile;
|
||||
|
||||
pSaveData = SV_SaveGameState();
|
||||
pSaveData = SV_SaveGameState( false );
|
||||
if( !pSaveData ) return 0;
|
||||
|
||||
SV_SaveFinish( pSaveData );
|
||||
|
@ -2127,9 +2144,7 @@ qboolean SV_LoadGame( const char *pPath )
|
|||
if( !FS_FileExists( pPath, true ))
|
||||
return false;
|
||||
|
||||
SV_ClearSaveDir();
|
||||
SV_InitGameProgs();
|
||||
|
||||
if( !svgame.hInstance )
|
||||
return false;
|
||||
|
||||
|
@ -2137,6 +2152,8 @@ qboolean SV_LoadGame( const char *pPath )
|
|||
|
||||
if( pFile )
|
||||
{
|
||||
SV_ClearGameState();
|
||||
|
||||
if( SV_SaveReadHeader( pFile, &gameHeader ))
|
||||
{
|
||||
SV_DirectoryExtract( pFile, gameHeader.mapCount );
|
||||
|
|
Reference in New Issue