cvar_t sv_gameplayfix_unstickentities = {0, "sv_gameplayfix_unstickentities", "1", "hack to check if entities are crossing world collision hull and try to move them to the right position"};
cvar_t sv_gameplayfix_fixedcheckwatertransition = {0, "sv_gameplayfix_fixedcheckwatertransition", "1", "fix two very stupid bugs in SV_CheckWaterTransition when watertype is CONTENTS_EMPTY (the bugs causes waterlevel to be 1 on first frame, -1 on second frame - the fix makes it 0 on both frames)"};
cvar_t sv_gravity = {CVAR_NOTIFY, "sv_gravity","800", "how fast you fall (512 = roughly earth gravity)"};
+cvar_t sv_init_frame_count = {0, "sv_init_frame_count", "2", "number of frames to run to allow everything to settle before letting clients connect"};
cvar_t sv_idealpitchscale = {0, "sv_idealpitchscale","0.8", "how much to look up/down slopes and stairs when not using freelook"};
cvar_t sv_jumpstep = {CVAR_NOTIFY, "sv_jumpstep", "0", "whether you can step up while jumping"};
cvar_t sv_jumpvelocity = {0, "sv_jumpvelocity", "270", "cvar that can be used by QuakeC code for jump velocity"};
cvar_t sv_autodemo_perclient_discardable = {CVAR_SAVE, "sv_autodemo_perclient_discardable", "0", "Allow game code to decide whether a demo should be kept or discarded."};
cvar_t halflifebsp = {0, "halflifebsp", "0", "indicates the current map is hlbsp format (useful to know because of different bounding box sizes)"};
+cvar_t sv_mapformat_is_quake2 = {0, "sv_mapformat_is_quake2", "0", "indicates the current map is q2bsp format (useful to know because of different entity behaviors, .frame on submodels and other things)"};
+cvar_t sv_mapformat_is_quake3 = {0, "sv_mapformat_is_quake3", "0", "indicates the current map is q2bsp format (useful to know because of different entity behaviors)"};
server_t sv;
server_static_t svs;
Cvar_RegisterVariable (&sv_gameplayfix_unstickentities);
Cvar_RegisterVariable (&sv_gameplayfix_fixedcheckwatertransition);
Cvar_RegisterVariable (&sv_gravity);
+ Cvar_RegisterVariable (&sv_init_frame_count);
Cvar_RegisterVariable (&sv_idealpitchscale);
Cvar_RegisterVariable (&sv_jumpstep);
Cvar_RegisterVariable (&sv_jumpvelocity);
Cvar_RegisterVariable (&sv_autodemo_perclient_discardable);
Cvar_RegisterVariable (&halflifebsp);
+ Cvar_RegisterVariable (&sv_mapformat_is_quake2);
+ Cvar_RegisterVariable (&sv_mapformat_is_quake3);
sv_mempool = Mem_AllocPool("server", 0, NULL);
}
{
client->csqcentityscope[i] = 0;
client->csqcentitysendflags[i] = 0xFFFFFF;
- client->csqcentityglobalhistory[i] = 0;
}
for (i = 0;i < NUM_CSQCENTITYDB_FRAMES;i++)
{
MSG_WriteString (&client->netconnection->message,message);
SV_StopDemoRecording(client); // to split up demos into different files
- if(sv_autodemo_perclient.integer && client->netconnection)
+ if(sv_autodemo_perclient.integer)
{
char demofile[MAX_OSPATH];
char ipaddress[MAX_QPATH];
if(client->netconnection && client->netconnection->crypto.authenticated)
{
- Con_Printf("%s connection to %s has been established: client is %s@%.*s, I am %.*s@%.*s\n",
+ Con_Printf("%s connection to %s has been established: client is %s@%s%.*s, I am %.*s@%s%.*s\n",
client->netconnection->crypto.use_aes ? "Encrypted" : "Authenticated",
client->netconnection->address,
client->netconnection->crypto.client_idfp[0] ? client->netconnection->crypto.client_idfp : "-",
+ (client->netconnection->crypto.client_issigned || !client->netconnection->crypto.client_keyfp[0]) ? "" : "~",
crypto_keyfp_recommended_length, client->netconnection->crypto.client_keyfp[0] ? client->netconnection->crypto.client_keyfp : "-",
crypto_keyfp_recommended_length, client->netconnection->crypto.server_idfp[0] ? client->netconnection->crypto.server_idfp : "-",
+ (client->netconnection->crypto.server_issigned || !client->netconnection->crypto.server_keyfp[0]) ? "" : "~",
crypto_keyfp_recommended_length, client->netconnection->crypto.server_keyfp[0] ? client->netconnection->crypto.server_keyfp : "-"
);
}
client->unreliablemsg.maxsize = sizeof(client->unreliablemsg_data);
// updated by receiving "rate" command from client, this is also the default if not using a DP client
client->rate = 1000000000;
- // no limits for local player
- if (client->netconnection && LHNETADDRESS_GetAddressType(&client->netconnection->peeraddress) == LHNETADDRESSTYPE_LOOP)
- client->rate = 1000000000;
client->connecttime = realtime;
if (!sv.loadgame)
}
// or not seen by random tracelines
- if (sv_cullentities_trace.integer && !isbmodel && sv.worldmodel->brush.TraceLineOfSight && !r_trippy.integer)
+ if (sv_cullentities_trace.integer && !isbmodel && sv.worldmodel && sv.worldmodel->brush.TraceLineOfSight && !r_trippy.integer)
{
int samples =
s->number <= svs.maxclients
MSG_WriteByte (msg, stats[STAT_NAILS]);
MSG_WriteByte (msg, stats[STAT_ROCKETS]);
MSG_WriteByte (msg, stats[STAT_CELLS]);
- if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_QUOTH || gamemode == GAME_NEXUIZ)
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_QUOTH || IS_OLDNEXUIZ_DERIVED(gamemode))
{
for (i = 0;i < 32;i++)
if (stats[STAT_ACTIVEWEAPON] & (1<<i))
sizebuf_t msg;
int stats[MAX_CL_STATS];
static unsigned char sv_sendclientdatagram_buf[NET_MAXMESSAGE];
+ double timedelta;
// obey rate limit by limiting packet frequency if the packet size
// limiting fails
//
// at very low rates (or very small sys_ticrate) the packet size is
// not reduced below 128, but packets may be sent less often
- maxsize = (int)(clientrate * sys_ticrate.value);
+
+ // how long are bursts?
+ timedelta = host_client->rate_burstsize / (double)client->rate;
+
+ // how much of the burst do we keep reserved?
+ timedelta *= 1 - net_burstreserve.value;
+
+ // only try to use excess time
+ timedelta = bound(0, realtime - host_client->netconnection->cleartime, timedelta);
+
+ // but we know next packet will be in sys_ticrate, so we can use up THAT bandwidth
+ timedelta += sys_ticrate.value;
+
+ // note: packet overhead (not counted in maxsize) is 28 bytes
+ maxsize = (int)(clientrate * timedelta) - 28;
+
+ // put it in sound bounds
maxsize = bound(128, maxsize, 1400);
maxsize2 = 1400;
+
// csqc entities can easily exceed 128 bytes, so disable throttling in
// mods that use csqc (they are likely to use less bandwidth anyway)
- if (sv.csqc_progsize > 0)
+ if((net_usesizelimit.integer == 1) ? (sv.csqc_progsize > 0) : (net_usesizelimit.integer < 1))
maxsize = maxsize2;
+
break;
}
SV_WriteDemoMessage(client, &msg, false);
// send the datagram
- NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate, client->sendsignon == 2);
+ NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate, client->rate_burstsize, client->sendsignon == 2);
if (client->sendsignon == 1 && !client->netconnection->message.cursize)
client->sendsignon = 2; // prevent reliable until client sends prespawn (this is the keepalive phase)
}
if (name == NULL)
name = "";
// always point the string back at host_client->name to keep it safe
- strlcpy (host_client->name, name, sizeof (host_client->name));
+ //strlcpy (host_client->name, name, sizeof (host_client->name));
+ if (name != host_client->name) // prevent buffer overlap SIGABRT on Mac OSX
+ strlcpy (host_client->name, name, sizeof (host_client->name));
PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(prog, host_client->name);
if (strcmp(host_client->old_name, host_client->name))
{
if (model == NULL)
model = "";
// always point the string back at host_client->name to keep it safe
- strlcpy (host_client->playermodel, model, sizeof (host_client->playermodel));
+ //strlcpy (host_client->playermodel, model, sizeof (host_client->playermodel));
+ if (model != host_client->playermodel) // prevent buffer overlap SIGABRT on Mac OSX
+ strlcpy (host_client->playermodel, model, sizeof (host_client->playermodel));
PRVM_serveredictstring(host_client->edict, playermodel) = PRVM_SetEngineString(prog, host_client->playermodel);
// NEXUIZ_PLAYERSKIN
if (skin == NULL)
skin = "";
// always point the string back at host_client->name to keep it safe
- strlcpy (host_client->playerskin, skin, sizeof (host_client->playerskin));
+ //strlcpy (host_client->playerskin, skin, sizeof (host_client->playerskin));
+ if (skin != host_client->playerskin) // prevent buffer overlap SIGABRT on Mac OSX
+ strlcpy (host_client->playerskin, skin, sizeof (host_client->playerskin));
PRVM_serveredictstring(host_client->edict, playerskin) = PRVM_SetEngineString(prog, host_client->playerskin);
// TODO: add an extension name for this [1/17/2008 Black]
// frags
host_client->frags = (int)PRVM_serveredictfloat(host_client->edict, frags);
- if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
+ if(IS_OLDNEXUIZ_DERIVED(gamemode))
if(!host_client->begun && host_client->netconnection)
host_client->frags = -666;
if (host_client->old_frags != host_client->frags)
{
if (argc == 2)
{
- for (effectnameindex = 1;effectnameindex < SV_MAX_PARTICLEEFFECTNAME;effectnameindex++)
+ for (effectnameindex = 1;effectnameindex < MAX_PARTICLEEFFECTNAME;effectnameindex++)
{
if (sv.particleeffectname[effectnameindex][0])
{
}
}
// if we run out of names, abort
- if (effectnameindex == SV_MAX_PARTICLEEFFECTNAME)
+ if (effectnameindex == MAX_PARTICLEEFFECTNAME)
{
Con_Printf("%s:%i: too many effects!\n", filename, linenumber);
break;
}
}
// search for the name
- for (effectnameindex = 1;effectnameindex < SV_MAX_PARTICLEEFFECTNAME && sv.particleeffectname[effectnameindex][0];effectnameindex++)
+ for (effectnameindex = 1;effectnameindex < MAX_PARTICLEEFFECTNAME && sv.particleeffectname[effectnameindex][0];effectnameindex++)
if (!strcmp(sv.particleeffectname[effectnameindex], name))
return effectnameindex;
// return 0 if we couldn't find it
cls.signon = 0;
Cvar_SetValue("halflifebsp", worldmodel->brush.ishlbsp);
+ Cvar_SetValue("sv_mapformat_is_quake2", worldmodel->brush.isq2bsp);
+ Cvar_SetValue("sv_mapformat_is_quake3", worldmodel->brush.isq3bsp);
if(*sv_random_seed.string)
{
// run two frames to allow everything to settle
sv.time = 1.0001;
- for (i = 0;i < 2;i++)
+ for (i = 0;i < sv_init_frame_count.integer;i++)
{
sv.frametime = 0.1;
SV_Physics ();
}
+ // Once all init frames have been run, we consider svqc code fully initialized.
+ prog->inittime = realtime;
+
if (cls.state == ca_dedicated)
Mod_PurgeUnused();
PRVM_serveredictstring(e, crypto_idfp) = PRVM_SetEngineString(prog, svs.clients[num].netconnection->crypto.client_idfp);
else
PRVM_serveredictstring(e, crypto_idfp) = 0;
+ PRVM_serveredictfloat(e, crypto_idfp_signed) = (svs.clients[num].netconnection != NULL && svs.clients[num].netconnection->crypto.authenticated && svs.clients[num].netconnection->crypto.client_issigned);
if(svs.clients[num].netconnection != NULL && svs.clients[num].netconnection->crypto.authenticated && svs.clients[num].netconnection->crypto.client_keyfp[0])
PRVM_serveredictstring(e, crypto_keyfp) = PRVM_SetEngineString(prog, svs.clients[num].netconnection->crypto.client_keyfp);
else
e = PRVM_NUM_FOR_EDICT(ed);
sv.csqcentityversion[e] = 0;
for (i = 0;i < svs.maxclients;i++)
- {
- if (svs.clients[i].csqcentityscope[e])
- svs.clients[i].csqcentityscope[e] = 1; // removed, awaiting send
svs.clients[i].csqcentitysendflags[e] = 0xFFFFFF;
- }
}
static void SVVM_count_edicts(prvm_prog_t *prog)