# Sv\_maxclients latched

**URL:** <https://discourse.ioquake.org/t/sv-maxclients-latched/886>\
**Category:** dev\
**Created:** [May 23, 2017, 1:57am UTC](https://discourse.ioquake.org/t/sv-maxclients-latched/886 "2017-05-23T01:57:51Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![sentry](https://avatars.discourse-cdn.com/v4/letter/s/439d5e/32.png) [@sentry](https://discourse.ioquake.org/u/sentry)\
**Post date:** [May 23, 2017, 1:57am UTC](https://discourse.ioquake.org/t/sv-maxclients-latched/886/1 "2017-05-23T01:57:51Z")

</div>

Is there a good reason why sv\_maxclients is latched and it’s not allowed to be updated instantly?

/qcommon/cvar.c

Inside of Cvar\_Set2, I changed

```auto
if (!force)

```

to

```auto
if (!force && strcmp(var_name,"sv_maxclients") != 0)

```

This prevents it from being latched. But, the problem is, when I issue the command it now immediately crashes the server.

---

<div class="post-metadata">

**Author:** ![zturtleman](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.ioquake.org/zturtleman/32/718_2.png) [@zturtleman](https://discourse.ioquake.org/u/zturtleman)\
**Post date:** [May 23, 2017, 1:18pm UTC](https://discourse.ioquake.org/t/sv-maxclients-latched/886/2 "2017-05-23T13:18:38Z")

</div>

Well, you found the reason. The server crashes when reading/writing past end of svs.clients (possibly snapshot entities array too, I don’t remember). Fun fact, UI’s trap\_Cvar\_SetValue( “sv\_maxclients”, 64 ) bypasses latch and crashes the local server.

I’m not sure if there is a particular reason changing sv\_maxclients is not supported though. Maybe to prevent excess memory allocating and freeing and having to handle dropping players in slots above sv\_maxclients mid-game.

---

<div class="post-metadata">

**Author:** ![sentry](https://avatars.discourse-cdn.com/v4/letter/s/439d5e/32.png) [@sentry](https://discourse.ioquake.org/u/sentry)\
**Post date:** [May 23, 2017, 5:44pm UTC](https://discourse.ioquake.org/t/sv-maxclients-latched/886/3 "2017-05-23T17:44:55Z")

</div>

Thanks for the insight! I’ll cross this one off of my list.

---

<div class="post-metadata">

**Author:** ![sentry](https://avatars.discourse-cdn.com/v4/letter/s/439d5e/32.png) [@sentry](https://discourse.ioquake.org/u/sentry)\
**Post date:** [May 26, 2017, 12:53am UTC](https://discourse.ioquake.org/t/sv-maxclients-latched/886/4 "2017-05-26T00:53:15Z")

</div>

I’m revisiting this topic because I’ve found that the Q3 servers at the CROM community: [ctf.cromctf.com](http://ctf.cromctf.com), [ffa.cromctf.com](http://ffa.cromctf.com) and [freeze.cromctf.com](http://freeze.cromctf.com) are able to update the maxclients cvar in realtime. If there’s 32 clients and the sv\_maxclients is set to 33 and a new client connects, it will immediately change the sv\_maxclients value to 34. So there has to be a solution to this question.

I wrote a function that runs every 10 seconds to increase/decrease the maxclients value. It’s not too useful without the ability to update it in realtime. In the [SV\_ChangeMaxClients() function](https://github.com/ariya/ioquake3/blob/master/code/server/sv_init.c#L298), would there be anything that I can comment out / do differently to prevent the server from crashing when modifying it in realtime?

```auto
void adjustMaxClients(void){

	#define MAXCLIENTS 48
	#define MINCLIENTS 32
	#define CLIENTDIFF 5
	#define CLIENTTHRESHOLD	3

	client_t *cl;
	int i, num = 0, newvalue;

	for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++){
		if(!cl->state){ continue; }
		num++;
	}

	// Do nothing if there's the maximum number of clients connected
	if(sv_maxclients->integer == MAXCLIENTS) {
		return;
	}

	// Example clients connected: 46
	if( num == MAXCLIENTS || num + CLIENTDIFF >= MAXCLIENTS ) {
		newvalue = MAXCLIENTS;
	}

	// Example clients connected: 28
	else if ( num + CLIENTTHRESHOLD <= MINCLIENTS ) {
		newvalue = MINCLIENTS; 
	}

	// Example clients connected: 35
	else {
		newvalue = num + CLIENTDIFF;
	}

	if( sv_maxclients->integer != newvalue ) {
		Cvar_Set( "sv_maxclients", itoa(newvalue) );
	}

}

```

---

<div class="post-metadata">

**Author:** ![zturtleman](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.ioquake.org/zturtleman/32/718_2.png) [@zturtleman](https://discourse.ioquake.org/u/zturtleman)\
**Post date:** [May 26, 2017, 4:23pm UTC](https://discourse.ioquake.org/t/sv-maxclients-latched/886/5 "2017-05-26T16:23:06Z")

</div>

Replace all references of sv\_maxclients-\>integer with (new variable) svs.maxclients. Once a frame check if sv\_maxclients-\>modified and update svs.clients / svs.maxclients (SV\_ChangeMaxClients) and set sv\_maxclients-\>modified to qfalse.

You’ll also need to change svs.snapshotEntities from being allocated on the hunk to zone (because hunk\_alloc can’t be freed). In SV\_ChangeMaxClients you’ll need to reallocate svs.snapshotEntities and copy the old data into it.

Or you could just set sv\_maxclients to the real max and screw with the value sent to players in infoResponse. Though, I honestly don’t understand the point.

---

<div class="post-metadata">

**Author:** ![sentry](https://avatars.discourse-cdn.com/v4/letter/s/439d5e/32.png) [@sentry](https://discourse.ioquake.org/u/sentry)\
**Post date:** [May 26, 2017, 8:53pm UTC](https://discourse.ioquake.org/t/sv-maxclients-latched/886/6 "2017-05-26T20:53:54Z")

</div>

Perfect. I think it would be easiest for me to do the latter! Thank you. I’ll post up my code when I’m done for others to reference on how to do it.

In the US 1.32c CTF community, in recent years some of larger servers have been hit with everything from amplification attacks to a nonstop barrage of fake clients connecting (\xff\xff\xff\xff connect ) with different IPs (socks servers). CROM was one of the communities that was hit the hardest by a rival server who I won’t name.

I’ve coded it so no more than 2 clients can connect from the same IP address. I’ve set-up an [iptables rate limiting policy](http://blog.alejandronolla.com/2013/08/05/amplification-ddos-attack-with-quake3-servers-an-analysis-2-slash-2/) to try and combat amplification. Automatically adjusting the maximum amount of players every that can connect every N amount of seconds was just one extra additional layer.

---

<div class="post-metadata">

**Author:** ![ensiform](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.ioquake.org/ensiform/32/234_2.png) [@ensiform](https://discourse.ioquake.org/u/ensiform)\
**Post date:** [June 4, 2017, 7:14pm UTC](https://discourse.ioquake.org/t/sv-maxclients-latched/886/7 "2017-06-04T19:14:14Z")

</div>

Use Cvar\_SetValue if you need to set a number rather than non-portable/non-standard itoa. Or Cvar\_Set with va("%d", value)

I don’t think setting the value is enough really. The gamecode caches the value on startup as level.maxclients and doesn’t update it until a map\_restart or new game VM load. Plus, you have to reallocate storage space in the clients buffer in the engine.
