/* ================== 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 * MAX_SNAPSHOT_ENTITIES; } else { // we don't need nearly as many when playing locally svs.numSnapshotEntities = sv_maxclients->integer * 4 * MAX_SNAPSHOT_ENTITIES; } }
/* =============== 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. =============== */ static 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 * MAX_SNAPSHOT_ENTITIES; } else { // we don't need nearly as many when playing locally svs.numSnapshotEntities = sv_maxclients->integer * 4 * MAX_SNAPSHOT_ENTITIES; } svs.initialized = qtrue; // Don't respect sv_killserver unless a server is actually running if ( sv_killserver->integer ) { Cvar_Set( "sv_killserver", "0" ); } Cvar_Set( "sv_running", "1" ); // Join the ipv6 multicast group now that a map is running so clients can scan for us on the local network. NET_JoinMulticast6(); }
/* =============== 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 = (struct client_s *)Z_Malloc (sizeof(client_t) * sv_maxclients->integer, TAG_CLIENTS, qtrue ); if ( com_dedicated->integer ) { svs.numSnapshotEntities = sv_maxclients->integer * PACKET_BACKUP * 64; Cvar_Set( "r_ghoul2animsmooth", "0"); Cvar_Set( "r_ghoul2unsqashaftersmooth", "0"); } else { // we don't need nearly as many when playing locally svs.numSnapshotEntities = sv_maxclients->integer * 4 * 64; } svs.initialized = qtrue; // Don't respect sv_killserver unless a server is actually running if ( sv_killserver->integer ) { Cvar_Set( "sv_killserver", "0" ); } Cvar_Set( "sv_running", "1" ); }
/* =============== 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_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 ); // RF, avoid trying to allocate large chunk on a fragmented zone svs.clients = calloc( sizeof( client_t ) * sv_maxclients->integer, 1 ); if ( !svs.clients ) { Com_Error( ERR_FATAL, "SV_Startup: unable to allocate svs.clients" ); } 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; #ifdef USE_HUB_SERVER // Try to resolve the hub once when the first ever // map is started on the server; we'll only try again if // sv_owHubHost was modified and the server was (soft) // restarted using SpawnServer() SV_ResolveowHubHost(); #endif Cvar_Set( "sv_running", "1" ); // Join the ipv6 multicast group now that a map is running so clients can scan for us on the local network. NET_JoinMulticast6(); }
/* =============== 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\n"); } SV_BoundMaxClients(1); // RF, avoid trying to allocate large chunk on a fragmented zone svs.clients = calloc(sizeof(client_t) * sv_maxclients->integer, 1); if (!svs.clients) { Com_Error(ERR_FATAL, "SV_Startup: unable to allocate svs.clients\n"); } 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"); #ifdef FEATURE_TRACKBASE TB_ServerStart(); #endif #ifdef FEATURE_MYSQL Com_DB_InitGameTest(); if (Com_DB_Ready() == 0) { Com_Printf("Database Functions Disabled.\n"); } else { Com_Printf("Database Functions Enabled.\n"); } #endif /* FEATURE_MYSQL */ }
/* =============== 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() { if( theSVS.initialized_ ) Com_Error( ERR_FATAL, "SV_Startup: svs.initialized" ); SV_BoundMaxClients( 1 ); //theSVS.clients_ = reinterpret_cast<SV_Client*>(Z_Malloc (sizeof(SV_Client) * sv_maxclients->integer )); theSVS.initClients(sv_maxclients->integer); // initializes clients to 0 (will be allocated once they join) if( com_dedicated->integer ) { theSVS.numSnapshotEntities_ = sv_maxclients->integer * PACKET_BACKUP * 64; } else { // we don't need nearly as many when playing locally theSVS.numSnapshotEntities_ = sv_maxclients->integer * 4 * 64; } theSVS.initialized_ = true; Cvar_Set( "sv_running", "1" ); }
/* =============== 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 ); // RF, avoid trying to allocate large chunk on a fragmented zone svs.clients = calloc( sizeof( client_t ) * sv_maxclients->integer, 1 ); if ( !svs.clients ) { Com_Error( ERR_FATAL, "SV_Startup: unable to allocate svs.clients" ); } //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() { // get the highest client number in use int count = 0; for( int i = 1 ; i <= sv_maxclients->integer ; i++ ) { SV_Client* cl = theSVS.svClients_.at(i); if( !cl ) continue; if( cl->state_ >= SV_Client::CS_CONNECTED ) { if( i > count ) count = i; } } count++; int 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; theSVS.changeMaxNumClients( sv_maxclients->integer, count ); // allocate New snapshot entities if( com_dedicated->integer ) { theSVS.numSnapshotEntities_ = sv_maxclients->integer * PACKET_BACKUP * 64; } else { // we don't need nearly as many when playing locally theSVS.numSnapshotEntities_ = sv_maxclients->integer * 4 * 64; } }
/* =============== 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 ); // RF, avoid trying to allocate large chunk on a fragmented zone svs.clients = ( client_t * ) calloc( sizeof( client_t ) * sv_maxclients->integer, 1 ); if ( !svs.clients ) { Com_Error( ERR_FATAL, "SV_Startup: unable to allocate svs.clients" ); } 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" ); #ifndef DEDICATED NET_Config( qtrue ); #endif // Join the IPv6 multicast group now that a map is running, so clients can scan for us on the local network. NET_JoinMulticast6(); }
/* =============== 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; SV_InitAllCGMessages(); // Don't respect sv_killserver unless a server is actually running if ( sv_killserver->integer ) { Cvar_Set( "sv_killserver", "0" ); } 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 ); free( svs.clients ); // RF, avoid trying to allocate large chunk on a fragmented zone // allocate new clients // RF, avoid trying to allocate large chunk on a fragmented zone svs.clients = calloc( sizeof( client_t ) * sv_maxclients->integer, 1 ); if ( !svs.clients ) { Com_Error( ERR_FATAL, "SV_Startup: unable to allocate svs.clients" ); } 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_ChangeMaxClients ================== */ void SV_ChangeMaxClients( void ) { int oldMaxClients; int i, j; client_t *oldClients; player_t *oldPlayers; int count; // get the highest client or player number in use count = 0; for ( i = 0 ; i < sv_maxclients->integer ; i++ ) { if ( svs.clients[i].state >= CS_CONNECTED || svs.players[i].inUse ) { 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) ); oldPlayers = Hunk_AllocateTempMemory( count * sizeof(player_t) ); // copy the clients and players to hunk memory for ( i = 0 ; i < count ; i++ ) { if ( svs.players[i].inUse && svs.players[i].client->state >= CS_CONNECTED ) { oldPlayers[i] = svs.players[i]; oldPlayers[i].client = NULL; // client pointer gets restored using localPlayers pointers. } else { Com_Memset(&oldPlayers[i], 0, sizeof(player_t)); } if ( svs.clients[i].state >= CS_CONNECTED ) { oldClients[i] = svs.clients[i]; // save player indexes for ( j = 0; j < MAX_SPLITVIEW; j++ ) { if (svs.clients[i].localPlayers[j]) { oldClients[i].localPlayers[j] = (void*)((svs.clients[i].localPlayers[j] - svs.players) + 1); } } } else { Com_Memset(&oldClients[i], 0, sizeof(client_t)); } } // free old clients and players arrays Z_Free( svs.clients ); Z_Free( svs.players ); // allocate new clients and players svs.clients = Z_Malloc ( sv_maxclients->integer * sizeof(client_t) ); Com_Memset( svs.clients, 0, sv_maxclients->integer * sizeof(client_t) ); svs.players = Z_Malloc ( sv_maxclients->integer * sizeof(player_t) ); Com_Memset( svs.players, 0, sv_maxclients->integer * sizeof(player_t) ); // copy the clients and players over for ( i = 0 ; i < count ; i++ ) { if ( oldPlayers[i].inUse ) { svs.players[i] = oldPlayers[i]; } if ( oldClients[i].state >= CS_CONNECTED ) { svs.clients[i] = oldClients[i]; // restore pointers for ( j = 0; j < MAX_SPLITVIEW; j++ ) { if (oldClients[i].localPlayers[j]) { svs.clients[i].localPlayers[j] = &svs.players[ (intptr_t)oldClients[i].localPlayers[j] - 1 ]; svs.clients[i].localPlayers[j]->client = &svs.clients[i]; } } } } // free the old playes and clients on the hunk Hunk_FreeTempMemory( oldPlayers ); Hunk_FreeTempMemory( oldClients ); // allocate new snapshot entities if ( !Com_GameIsSinglePlayer() ) { svs.numSnapshotEntities = sv_maxclients->integer * PACKET_BACKUP * MAX_SNAPSHOT_ENTITIES; } else { // we don't need nearly as many when playing locally svs.numSnapshotEntities = sv_maxclients->integer * 4 * MAX_SNAPSHOT_ENTITIES; } }
/* ================== SV_DemoChangeMaxClients change sv_maxclients and move real clients slots when a demo is playing or stopped ================== */ void SV_DemoChangeMaxClients(void) { int oldMaxClients, oldDemoClients; int i, j, k; client_t *oldClients = NULL; int count; //qboolean firstTime = svs.clients == NULL; // == Checking the prerequisites // Note: we check here that we have enough slots to fit all clients, and that it doesn't overflow the MAX_CLIENTS the engine can support. Also, we save the oldMaxClients and oldDemoClients values. // -- 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++; // -- Save the previous oldMaxClients and oldDemoClients values, and update // Save the previous sv_maxclients value before updating it oldMaxClients = sv_maxclients->integer; // update the cvars Cvar_Get("sv_maxclients", "8", 0); Cvar_Get("sv_democlients", "0", 0); // unnecessary now that sv_democlients is not latched anymore? // Save the previous sv_democlients (since it's updated instantly, we cannot get it directly), we use a trick by computing the difference between the new and previous sv_maxclients (the difference should indeed be the exact value of sv_democlients) oldDemoClients = (oldMaxClients - sv_maxclients->integer); if (oldDemoClients < 0) // if the difference is negative, this means that before it was set to 0 (because the newer sv_maxclients is greater than the old) { oldDemoClients = 0; } // -- Check limits // never go below the highest client number in use (make sure we have enough room for all players) SV_BoundMaxClients(count); // -- Change check: if still the same, we just quit, there's nothing to do if (sv_maxclients->integer == oldMaxClients) { return; } // == Memorizing clients // Note: we save in a temporary variables the clients, because after we will wipe completely the svs.clients struct // copy the clients to hunk memory oldClients = Hunk_AllocateTempMemory((sv_maxclients->integer - sv_democlients->integer) * sizeof(client_t)); // we allocate just enough memory for the real clients (not counting in the democlients) // For all previous clients slots, we copy the entire client into a temporary var for (i = 0, j = 0, k = sv_privateClients->integer ; i < oldMaxClients ; i++) // for all the previously connected clients, we copy them to a temporary var { // If there is a real client in this slot if (svs.clients[i].state >= CS_CONNECTED) { // if the client is in a privateClient reserved slot, we move him on the reserved slots if (i >= oldDemoClients && i < oldDemoClients + sv_privateClients->integer) { oldClients[j++] = svs.clients[i]; // else the client is not a privateClient, and we move him to the first available slot after the privateClients slots } else { oldClients[k++] = svs.clients[i]; } } } // Fill in the remaining clients slots with empty clients (else the engine crash when copying into memory svs.clients) for (i = j; i < sv_privateClients->integer; i++) // Fill the privateClients empty slots { Com_Memset(&oldClients[i], 0, sizeof(client_t)); } for (i = k; i < (sv_maxclients->integer - sv_democlients->integer); i++) // Fill the other normal clients slots { Com_Memset(&oldClients[i], 0, sizeof(client_t)); } // free old clients arrays Z_Free(svs.clients); // == Allocating the new svs.clients and moving the saved clients over from the temporary var // allocate new svs.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 (and move them depending on sv_democlients: if >0, move them upwards, if == 0, move them to their original slots) Com_Memcpy(svs.clients + sv_democlients->integer, oldClients, (sv_maxclients->integer - sv_democlients->integer) * sizeof(client_t)); // free the old clients on the hunk Hunk_FreeTempMemory(oldClients); // == Allocating snapshot entities // 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; } // == Server-side demos management // set demostate to none if it was just waiting to set maxclients and move real clients slots if (sv.demoState == DS_WAITINGSTOP) { sv.demoState = DS_NONE; Cvar_SetValue("sv_demoState", DS_NONE); } }