diff options
Diffstat (limited to 'ioq3-r437/src/server/sv_init.c')
-rw-r--r-- | ioq3-r437/src/server/sv_init.c | 701 |
1 files changed, 0 insertions, 701 deletions
diff --git a/ioq3-r437/src/server/sv_init.c b/ioq3-r437/src/server/sv_init.c deleted file mode 100644 index 4ce424ee..00000000 --- a/ioq3-r437/src/server/sv_init.c +++ /dev/null @@ -1,701 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "server.h" - -/* -=============== -SV_SetConfigstring - -=============== -*/ -void SV_SetConfigstring (int index, const char *val) { - int len, i; - int maxChunkSize = MAX_STRING_CHARS - 24; - client_t *client; - - if ( index < 0 || index >= MAX_CONFIGSTRINGS ) { - Com_Error (ERR_DROP, "SV_SetConfigstring: bad index %i\n", index); - } - - if ( !val ) { - val = ""; - } - - // don't bother broadcasting an update if no change - if ( !strcmp( val, sv.configstrings[ index ] ) ) { - return; - } - - // change the string in sv - Z_Free( sv.configstrings[index] ); - sv.configstrings[index] = CopyString( val ); - - // send it to all the clients if we aren't - // spawning a new server - if ( sv.state == SS_GAME || sv.restarting ) { - - // send the data to all relevent clients - for (i = 0, client = svs.clients; i < sv_maxclients->integer ; i++, client++) { - if ( client->state < CS_PRIMED ) { - continue; - } - // do not always send server info to all clients - if ( index == CS_SERVERINFO && client->gentity && (client->gentity->r.svFlags & SVF_NOSERVERINFO) ) { - continue; - } - - len = strlen( val ); - if( len >= maxChunkSize ) { - int sent = 0; - int remaining = len; - char *cmd; - char buf[MAX_STRING_CHARS]; - - while (remaining > 0 ) { - if ( sent == 0 ) { - cmd = "bcs0"; - } - else if( remaining < maxChunkSize ) { - cmd = "bcs2"; - } - else { - cmd = "bcs1"; - } - Q_strncpyz( buf, &val[sent], maxChunkSize ); - - SV_SendServerCommand( client, "%s %i \"%s\"\n", cmd, index, buf ); - - sent += (maxChunkSize - 1); - remaining -= (maxChunkSize - 1); - } - } else { - // standard cs, just send it - SV_SendServerCommand( client, "cs %i \"%s\"\n", index, val ); - } - } - } -} - - - -/* -=============== -SV_GetConfigstring - -=============== -*/ -void SV_GetConfigstring( int index, char *buffer, int bufferSize ) { - if ( bufferSize < 1 ) { - Com_Error( ERR_DROP, "SV_GetConfigstring: bufferSize == %i", bufferSize ); - } - if ( index < 0 || index >= MAX_CONFIGSTRINGS ) { - Com_Error (ERR_DROP, "SV_GetConfigstring: bad index %i\n", index); - } - if ( !sv.configstrings[index] ) { - buffer[0] = 0; - return; - } - - Q_strncpyz( buffer, sv.configstrings[index], bufferSize ); -} - - -/* -=============== -SV_SetUserinfo - -=============== -*/ -void SV_SetUserinfo( int index, const char *val ) { - if ( index < 0 || index >= sv_maxclients->integer ) { - Com_Error (ERR_DROP, "SV_SetUserinfo: bad index %i\n", index); - } - - if ( !val ) { - val = ""; - } - - Q_strncpyz( svs.clients[index].userinfo, val, sizeof( svs.clients[ index ].userinfo ) ); - Q_strncpyz( svs.clients[index].name, Info_ValueForKey( val, "name" ), sizeof(svs.clients[index].name) ); -} - - - -/* -=============== -SV_GetUserinfo - -=============== -*/ -void SV_GetUserinfo( int index, char *buffer, int bufferSize ) { - if ( bufferSize < 1 ) { - Com_Error( ERR_DROP, "SV_GetUserinfo: bufferSize == %i", bufferSize ); - } - if ( index < 0 || index >= sv_maxclients->integer ) { - Com_Error (ERR_DROP, "SV_GetUserinfo: bad index %i\n", index); - } - Q_strncpyz( buffer, svs.clients[ index ].userinfo, bufferSize ); -} - - -/* -================ -SV_CreateBaseline - -Entity baselines are used to compress non-delta messages -to the clients -- only the fields that differ from the -baseline will be transmitted -================ -*/ -void SV_CreateBaseline( void ) { - sharedEntity_t *svent; - int entnum; - - for ( entnum = 1; entnum < sv.num_entities ; entnum++ ) { - svent = SV_GentityNum(entnum); - if (!svent->r.linked) { - continue; - } - svent->s.number = entnum; - - // - // take current state as baseline - // - sv.svEntities[entnum].baseline = svent->s; - } -} - - -/* -=============== -SV_BoundMaxClients - -=============== -*/ -void SV_BoundMaxClients( int minimum ) { - // get the current maxclients value - Cvar_Get( "sv_maxclients", "8", 0 ); - - sv_maxclients->modified = qfalse; - - if ( sv_maxclients->integer < minimum ) { - Cvar_Set( "sv_maxclients", va("%i", minimum) ); - } else if ( sv_maxclients->integer > MAX_CLIENTS ) { - Cvar_Set( "sv_maxclients", va("%i", MAX_CLIENTS) ); - } -} - - -/* -=============== -SV_Startup - -Called when a host starts a map when it wasn't running -one before. Successive map or map_restart commands will -NOT cause this to be called, unless the game is exited to -the menu system first. -=============== -*/ -void SV_Startup( void ) { - if ( svs.initialized ) { - Com_Error( ERR_FATAL, "SV_Startup: svs.initialized" ); - } - SV_BoundMaxClients( 1 ); - - svs.clients = Z_Malloc (sizeof(client_t) * sv_maxclients->integer ); - if ( com_dedicated->integer ) { - svs.numSnapshotEntities = sv_maxclients->integer * PACKET_BACKUP * 64; - } else { - // we don't need nearly as many when playing locally - svs.numSnapshotEntities = sv_maxclients->integer * 4 * 64; - } - svs.initialized = qtrue; - - Cvar_Set( "sv_running", "1" ); -} - - -/* -================== -SV_ChangeMaxClients -================== -*/ -void SV_ChangeMaxClients( void ) { - int oldMaxClients; - int i; - client_t *oldClients; - int count; - - // get the highest client number in use - count = 0; - for ( i = 0 ; i < sv_maxclients->integer ; i++ ) { - if ( svs.clients[i].state >= CS_CONNECTED ) { - if (i > count) - count = i; - } - } - count++; - - oldMaxClients = sv_maxclients->integer; - // never go below the highest client number in use - SV_BoundMaxClients( count ); - // if still the same - if ( sv_maxclients->integer == oldMaxClients ) { - return; - } - - oldClients = Hunk_AllocateTempMemory( count * sizeof(client_t) ); - // copy the clients to hunk memory - for ( i = 0 ; i < count ; i++ ) { - if ( svs.clients[i].state >= CS_CONNECTED ) { - oldClients[i] = svs.clients[i]; - } - else { - Com_Memset(&oldClients[i], 0, sizeof(client_t)); - } - } - - // free old clients arrays - Z_Free( svs.clients ); - - // allocate new clients - svs.clients = Z_Malloc ( sv_maxclients->integer * sizeof(client_t) ); - Com_Memset( svs.clients, 0, sv_maxclients->integer * sizeof(client_t) ); - - // copy the clients over - for ( i = 0 ; i < count ; i++ ) { - if ( oldClients[i].state >= CS_CONNECTED ) { - svs.clients[i] = oldClients[i]; - } - } - - // free the old clients on the hunk - Hunk_FreeTempMemory( oldClients ); - - // allocate new snapshot entities - if ( com_dedicated->integer ) { - svs.numSnapshotEntities = sv_maxclients->integer * PACKET_BACKUP * 64; - } else { - // we don't need nearly as many when playing locally - svs.numSnapshotEntities = sv_maxclients->integer * 4 * 64; - } -} - -/* -================ -SV_ClearServer -================ -*/ -void SV_ClearServer(void) { - int i; - - for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) { - if ( sv.configstrings[i] ) { - Z_Free( sv.configstrings[i] ); - } - } - Com_Memset (&sv, 0, sizeof(sv)); -} - -/* -================ -SV_TouchCGame - - touch the cgame.vm so that a pure client can load it if it's in a seperate pk3 -================ -*/ -void SV_TouchCGame(void) { - fileHandle_t f; - char filename[MAX_QPATH]; - - Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", "cgame" ); - FS_FOpenFileRead( filename, &f, qfalse ); - if ( f ) { - FS_FCloseFile( f ); - } -} - -/* -================ -SV_SpawnServer - -Change the server to a new map, taking all connected -clients along with it. -This is NOT called for map_restart -================ -*/ -void SV_SpawnServer( char *server, qboolean killBots ) { - int i; - int checksum; - qboolean isBot; - char systemInfo[16384]; - const char *p; - - // shut down the existing game if it is running - SV_ShutdownGameProgs(); - - Com_Printf ("------ Server Initialization ------\n"); - Com_Printf ("Server: %s\n",server); - - // if not running a dedicated server CL_MapLoading will connect the client to the server - // also print some status stuff - CL_MapLoading(); - - // make sure all the client stuff is unloaded - CL_ShutdownAll(); - - // clear the whole hunk because we're (re)loading the server - Hunk_Clear(); - - // clear collision map data - CM_ClearMap(); - - // init client structures and svs.numSnapshotEntities - if ( !Cvar_VariableValue("sv_running") ) { - SV_Startup(); - } else { - // check for maxclients change - if ( sv_maxclients->modified ) { - SV_ChangeMaxClients(); - } - } - - // clear pak references - FS_ClearPakReferences(0); - - // allocate the snapshot entities on the hunk - svs.snapshotEntities = Hunk_Alloc( sizeof(entityState_t)*svs.numSnapshotEntities, h_high ); - svs.nextSnapshotEntities = 0; - - // toggle the server bit so clients can detect that a - // server has changed - svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT; - - // set nextmap to the same map, but it may be overriden - // by the game startup or another console command - Cvar_Set( "nextmap", "map_restart 0"); -// Cvar_Set( "nextmap", va("map %s", server) ); - - for (i=0 ; i<sv_maxclients->integer ; i++) { - // save when the server started for each client already connected - if (svs.clients[i].state >= CS_CONNECTED) { - svs.clients[i].oldServerTime = sv.time; - } - } - - // wipe the entire per-level structure - SV_ClearServer(); - for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) { - sv.configstrings[i] = CopyString(""); - } - - // make sure we are not paused - Cvar_Set("cl_paused", "0"); - - // get a new checksum feed and restart the file system - srand(Com_Milliseconds()); - sv.checksumFeed = ( ((int) rand() << 16) ^ rand() ) ^ Com_Milliseconds(); - FS_Restart( sv.checksumFeed ); - - CM_LoadMap( va("maps/%s.bsp", server), qfalse, &checksum ); - - // set serverinfo visible name - Cvar_Set( "mapname", server ); - - Cvar_Set( "sv_mapChecksum", va("%i",checksum) ); - - // serverid should be different each time - sv.serverId = com_frameTime; - sv.restartedServerId = sv.serverId; // I suppose the init here is just to be safe - sv.checksumFeedServerId = sv.serverId; - Cvar_Set( "sv_serverid", va("%i", sv.serverId ) ); - - // clear physics interaction links - SV_ClearWorld (); - - // media configstring setting should be done during - // the loading stage, so connected clients don't have - // to load during actual gameplay - sv.state = SS_LOADING; - - // load and spawn all other entities - SV_InitGameProgs(); - - // don't allow a map_restart if game is modified - sv_gametype->modified = qfalse; - - // run a few frames to allow everything to settle - for (i = 0;i < 3; i++) - { - VM_Call (gvm, GAME_RUN_FRAME, sv.time); - SV_BotFrame (sv.time); - sv.time += 100; - svs.time += 100; - } - - // create a baseline for more efficient communications - SV_CreateBaseline (); - - for (i=0 ; i<sv_maxclients->integer ; i++) { - // send the new gamestate to all connected clients - if (svs.clients[i].state >= CS_CONNECTED) { - char *denied; - - if ( svs.clients[i].netchan.remoteAddress.type == NA_BOT ) { - if ( killBots ) { - SV_DropClient( &svs.clients[i], "" ); - continue; - } - isBot = qtrue; - } - else { - isBot = qfalse; - } - - // connect the client again - denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) ); // firstTime = qfalse - if ( denied ) { - // this generally shouldn't happen, because the client - // was connected before the level change - SV_DropClient( &svs.clients[i], denied ); - } else { - if( !isBot ) { - // when we get the next packet from a connected client, - // the new gamestate will be sent - svs.clients[i].state = CS_CONNECTED; - } - else { - client_t *client; - sharedEntity_t *ent; - - client = &svs.clients[i]; - client->state = CS_ACTIVE; - ent = SV_GentityNum( i ); - ent->s.number = i; - client->gentity = ent; - - client->deltaMessage = -1; - client->nextSnapshotTime = svs.time; // generate a snapshot immediately - - VM_Call( gvm, GAME_CLIENT_BEGIN, i ); - } - } - } - } - - // run another frame to allow things to look at all the players - VM_Call (gvm, GAME_RUN_FRAME, sv.time); - SV_BotFrame (sv.time); - sv.time += 100; - svs.time += 100; - - if ( sv_pure->integer ) { - // the server sends these to the clients so they will only - // load pk3s also loaded at the server - p = FS_LoadedPakChecksums(); - Cvar_Set( "sv_paks", p ); - if (strlen(p) == 0) { - Com_Printf( "WARNING: sv_pure set but no PK3 files loaded\n" ); - } - p = FS_LoadedPakNames(); - Cvar_Set( "sv_pakNames", p ); - - // if a dedicated pure server we need to touch the cgame because it could be in a - // seperate pk3 file and the client will need to load the latest cgame.qvm - if ( com_dedicated->integer ) { - SV_TouchCGame(); - } - } - else { - Cvar_Set( "sv_paks", "" ); - Cvar_Set( "sv_pakNames", "" ); - } - // the server sends these to the clients so they can figure - // out which pk3s should be auto-downloaded - p = FS_ReferencedPakChecksums(); - Cvar_Set( "sv_referencedPaks", p ); - p = FS_ReferencedPakNames(); - Cvar_Set( "sv_referencedPakNames", p ); - - // save systeminfo and serverinfo strings - Q_strncpyz( systemInfo, Cvar_InfoString_Big( CVAR_SYSTEMINFO ), sizeof( systemInfo ) ); - cvar_modifiedFlags &= ~CVAR_SYSTEMINFO; - SV_SetConfigstring( CS_SYSTEMINFO, systemInfo ); - - SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) ); - cvar_modifiedFlags &= ~CVAR_SERVERINFO; - - // any media configstring setting now should issue a warning - // and any configstring changes should be reliably transmitted - // to all clients - sv.state = SS_GAME; - - // send a heartbeat now so the master will get up to date info - SV_Heartbeat_f(); - - Hunk_SetMark(); - - Com_Printf ("-----------------------------------\n"); -} - -/* -=============== -SV_Init - -Only called at main exe startup, not for each game -=============== -*/ -void SV_BotInitBotLib(void); - -void SV_Init (void) { - SV_AddOperatorCommands (); - - // serverinfo vars - Cvar_Get ("dmflags", "0", CVAR_SERVERINFO); - Cvar_Get ("fraglimit", "20", CVAR_SERVERINFO); - Cvar_Get ("timelimit", "0", CVAR_SERVERINFO); - sv_gametype = Cvar_Get ("g_gametype", "0", CVAR_SERVERINFO | CVAR_LATCH ); - Cvar_Get ("sv_keywords", "", CVAR_SERVERINFO); - Cvar_Get ("protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_ROM); - sv_mapname = Cvar_Get ("mapname", "nomap", CVAR_SERVERINFO | CVAR_ROM); - sv_privateClients = Cvar_Get ("sv_privateClients", "0", CVAR_SERVERINFO); - sv_hostname = Cvar_Get ("sv_hostname", "noname", CVAR_SERVERINFO | CVAR_ARCHIVE ); - sv_maxclients = Cvar_Get ("sv_maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH); - - sv_maxRate = Cvar_Get ("sv_maxRate", "0", CVAR_ARCHIVE | CVAR_SERVERINFO ); - sv_minPing = Cvar_Get ("sv_minPing", "0", CVAR_ARCHIVE | CVAR_SERVERINFO ); - sv_maxPing = Cvar_Get ("sv_maxPing", "0", CVAR_ARCHIVE | CVAR_SERVERINFO ); - sv_floodProtect = Cvar_Get ("sv_floodProtect", "1", CVAR_ARCHIVE | CVAR_SERVERINFO ); - - // systeminfo - Cvar_Get ("sv_cheats", "1", CVAR_SYSTEMINFO | CVAR_ROM ); - sv_serverid = Cvar_Get ("sv_serverid", "0", CVAR_SYSTEMINFO | CVAR_ROM ); - sv_pure = Cvar_Get ("sv_pure", "1", CVAR_SYSTEMINFO ); - Cvar_Get ("sv_paks", "", CVAR_SYSTEMINFO | CVAR_ROM ); - Cvar_Get ("sv_pakNames", "", CVAR_SYSTEMINFO | CVAR_ROM ); - Cvar_Get ("sv_referencedPaks", "", CVAR_SYSTEMINFO | CVAR_ROM ); - Cvar_Get ("sv_referencedPakNames", "", CVAR_SYSTEMINFO | CVAR_ROM ); - - // server vars - sv_rconPassword = Cvar_Get ("rconPassword", "", CVAR_TEMP ); - sv_privatePassword = Cvar_Get ("sv_privatePassword", "", CVAR_TEMP ); - sv_fps = Cvar_Get ("sv_fps", "20", CVAR_TEMP ); - sv_timeout = Cvar_Get ("sv_timeout", "200", CVAR_TEMP ); - sv_zombietime = Cvar_Get ("sv_zombietime", "2", CVAR_TEMP ); - Cvar_Get ("nextmap", "", CVAR_TEMP ); - - sv_allowDownload = Cvar_Get ("sv_allowDownload", "0", CVAR_SERVERINFO); - sv_master[0] = Cvar_Get ("sv_master1", MASTER_SERVER_NAME, 0 ); - sv_master[1] = Cvar_Get ("sv_master2", "", CVAR_ARCHIVE ); - sv_master[2] = Cvar_Get ("sv_master3", "", CVAR_ARCHIVE ); - sv_master[3] = Cvar_Get ("sv_master4", "", CVAR_ARCHIVE ); - sv_master[4] = Cvar_Get ("sv_master5", "", CVAR_ARCHIVE ); - sv_reconnectlimit = Cvar_Get ("sv_reconnectlimit", "3", 0); - sv_showloss = Cvar_Get ("sv_showloss", "0", 0); - sv_padPackets = Cvar_Get ("sv_padPackets", "0", 0); - sv_killserver = Cvar_Get ("sv_killserver", "0", 0); - sv_mapChecksum = Cvar_Get ("sv_mapChecksum", "", CVAR_ROM); - sv_lanForceRate = Cvar_Get ("sv_lanForceRate", "1", CVAR_ARCHIVE ); - sv_strictAuth = Cvar_Get ("sv_strictAuth", "1", CVAR_ARCHIVE ); - - // initialize bot cvars so they are listed and can be set before loading the botlib - SV_BotInitCvars(); - - // init the botlib here because we need the pre-compiler in the UI - SV_BotInitBotLib(); -} - - -/* -================== -SV_FinalMessage - -Used by SV_Shutdown to send a final message to all -connected clients before the server goes down. The messages are sent immediately, -not just stuck on the outgoing message list, because the server is going -to totally exit after returning from this function. -================== -*/ -void SV_FinalMessage( char *message ) { - int i, j; - client_t *cl; - - // send it twice, ignoring rate - for ( j = 0 ; j < 2 ; j++ ) { - for (i=0, cl = svs.clients ; i < sv_maxclients->integer ; i++, cl++) { - if (cl->state >= CS_CONNECTED) { - // don't send a disconnect to a local client - if ( cl->netchan.remoteAddress.type != NA_LOOPBACK ) { - SV_SendServerCommand( cl, "print \"%s\"", message ); - SV_SendServerCommand( cl, "disconnect" ); - } - // force a snapshot to be sent - cl->nextSnapshotTime = -1; - SV_SendClientSnapshot( cl ); - } - } - } -} - - -/* -================ -SV_Shutdown - -Called when each game quits, -before Sys_Quit or Sys_Error -================ -*/ -void SV_Shutdown( char *finalmsg ) { - if ( !com_sv_running || !com_sv_running->integer ) { - return; - } - - Com_Printf( "----- Server Shutdown -----\n" ); - - if ( svs.clients && !com_errorEntered ) { - SV_FinalMessage( finalmsg ); - } - - SV_RemoveOperatorCommands(); - SV_MasterShutdown(); - SV_ShutdownGameProgs(); - - // free current level - SV_ClearServer(); - - // free server static data - if ( svs.clients ) { - Z_Free( svs.clients ); - } - Com_Memset( &svs, 0, sizeof( svs ) ); - - Cvar_Set( "sv_running", "0" ); - Cvar_Set("ui_singlePlayerActive", "0"); - - Com_Printf( "---------------------------\n" ); - - // disconnect any local clients - CL_Disconnect( qfalse ); -} - |