X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=sv_main.c;h=0b81820b51e708b395756505ee4d600dc79b5e59;hp=bd61ccc5ec0639d93e9bb1c1a5b0921e6e8ed2c6;hb=2075ae43356d724bae305ce8fd36ea570718b14a;hpb=366229127dad0794355c9daf8e17c833624b3d80 diff --git a/sv_main.c b/sv_main.c index bd61ccc5..0b81820b 100644 --- a/sv_main.c +++ b/sv_main.c @@ -81,6 +81,8 @@ cvar_t sv_cullentities_trace = {0, "sv_cullentities_trace", "0", "somewhat slow cvar_t sv_cullentities_trace_delay = {0, "sv_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"}; cvar_t sv_cullentities_trace_delay_players = {0, "sv_cullentities_trace_delay_players", "0.2", "number of seconds until the entity gets actually culled if it is a player entity"}; cvar_t sv_cullentities_trace_enlarge = {0, "sv_cullentities_trace_enlarge", "0", "box enlargement for entity culling"}; +cvar_t sv_cullentities_trace_expand = { 0, "sv_cullentities_trace_expand", "0", "box is expanded by this many units for entity culling" }; +cvar_t sv_cullentities_trace_eyejitter = {0, "sv_cullentities_trace_eyejitter", "16", "jitter the eye by this much for each trace"}; cvar_t sv_cullentities_trace_prediction = {0, "sv_cullentities_trace_prediction", "1", "also trace from the predicted player position"}; cvar_t sv_cullentities_trace_prediction_time = {0, "sv_cullentities_trace_prediction_time", "0.2", "how many seconds of prediction to use"}; cvar_t sv_cullentities_trace_entityocclusion = {0, "sv_cullentities_trace_entityocclusion", "0", "also check if doors and other bsp models are in the way"}; @@ -114,7 +116,7 @@ cvar_t sv_gameplayfix_setmodelrealbox = {0, "sv_gameplayfix_setmodelrealbox", "1 cvar_t sv_gameplayfix_slidemoveprojectiles = {0, "sv_gameplayfix_slidemoveprojectiles", "1", "allows MOVETYPE_FLY/FLYMISSILE/TOSS/BOUNCE/BOUNCEMISSILE entities to finish their move in a frame even if they hit something, fixes 'gravity accumulation' bug for grenades on steep slopes"}; cvar_t sv_gameplayfix_stepdown = {0, "sv_gameplayfix_stepdown", "0", "attempts to step down stairs, not just up them (prevents the familiar thud..thud..thud.. when running down stairs and slopes)"}; cvar_t sv_gameplayfix_stepmultipletimes = {0, "sv_gameplayfix_stepmultipletimes", "0", "applies step-up onto a ledge more than once in a single frame, when running quickly up stairs"}; -cvar_t sv_gameplayfix_nostepmoveonsteepslopes = {0, "sv_gameplayfix_nostepmoveonsteepslopes", "0", "grude fix which prevents MOVETYPE_STEP (not swimming or flying) to move on slopes whose angle is bigger than 45 degree"}; +cvar_t sv_gameplayfix_nostepmoveonsteepslopes = {0, "sv_gameplayfix_nostepmoveonsteepslopes", "0", "crude fix which prevents MOVETYPE_STEP (not swimming or flying) to move on slopes whose angle is bigger than 45 degree"}; cvar_t sv_gameplayfix_swiminbmodels = {0, "sv_gameplayfix_swiminbmodels", "1", "causes pointcontents (used to determine if you are in a liquid) to check bmodel entities as well as the world model, so you can swim around in (possibly moving) water bmodel entities"}; cvar_t sv_gameplayfix_upwardvelocityclearsongroundflag = {0, "sv_gameplayfix_upwardvelocityclearsongroundflag", "1", "prevents monsters, items, and most other objects from being stuck to the floor when pushed around by damage, and other situations in mods"}; cvar_t sv_gameplayfix_downtracesupportsongroundflag = {0, "sv_gameplayfix_downtracesupportsongroundflag", "1", "prevents very short moves from clearing onground (which may make the player stick to the floor at high netfps)"}; @@ -123,6 +125,7 @@ cvar_t sv_gameplayfix_unstickplayers = {0, "sv_gameplayfix_unstickplayers", "1", 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"}; @@ -193,6 +196,8 @@ cvar_t sv_autodemo_perclient_nameformat = {CVAR_SAVE, "sv_autodemo_perclient_nam 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; @@ -490,6 +495,8 @@ void SV_Init (void) Cvar_RegisterVariable (&sv_cullentities_trace_delay); Cvar_RegisterVariable (&sv_cullentities_trace_delay_players); Cvar_RegisterVariable (&sv_cullentities_trace_enlarge); + Cvar_RegisterVariable (&sv_cullentities_trace_expand); + Cvar_RegisterVariable (&sv_cullentities_trace_eyejitter); Cvar_RegisterVariable (&sv_cullentities_trace_entityocclusion); Cvar_RegisterVariable (&sv_cullentities_trace_prediction); Cvar_RegisterVariable (&sv_cullentities_trace_prediction_time); @@ -532,6 +539,7 @@ void SV_Init (void) 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); @@ -603,6 +611,8 @@ void SV_Init (void) 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); } @@ -704,7 +714,7 @@ Larger attenuations will drop off. (max 4 attenuation) ================== */ -void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int volume, float attenuation, qboolean reliable, float speed) +void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int nvolume, float attenuation, qboolean reliable, float speed) { prvm_prog_t *prog = SVVM_prog; sizebuf_t *dest; @@ -712,9 +722,9 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v dest = (reliable ? &sv.reliable_datagram : &sv.datagram); - if (volume < 0 || volume > 255) + if (nvolume < 0 || nvolume > 255) { - Con_Printf ("SV_StartSound: volume = %i\n", volume); + Con_Printf ("SV_StartSound: volume = %i\n", nvolume); return; } @@ -744,7 +754,7 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v speed4000 = (int)floor(speed * 4000.0f + 0.5f); field_mask = 0; - if (volume != DEFAULT_SOUND_PACKET_VOLUME) + if (nvolume != DEFAULT_SOUND_PACKET_VOLUME) field_mask |= SND_VOLUME; if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION) field_mask |= SND_ATTENUATION; @@ -759,7 +769,7 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v MSG_WriteByte (dest, svc_sound); MSG_WriteByte (dest, field_mask); if (field_mask & SND_VOLUME) - MSG_WriteByte (dest, volume); + MSG_WriteByte (dest, nvolume); if (field_mask & SND_ATTENUATION) MSG_WriteByte (dest, (int)(attenuation*64)); if (field_mask & SND_SPEEDUSHORT4000) @@ -796,13 +806,13 @@ function, therefore the check for it is omitted. ================== */ -void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float attenuation, float speed) +void SV_StartPointSound (vec3_t origin, const char *sample, int nvolume, float attenuation, float speed) { int sound_num, field_mask, i, speed4000; - if (volume < 0 || volume > 255) + if (nvolume < 0 || nvolume > 255) { - Con_Printf ("SV_StartPointSound: volume = %i\n", volume); + Con_Printf ("SV_StartPointSound: volume = %i\n", nvolume); return; } @@ -822,7 +832,7 @@ void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float at speed4000 = (int)(speed * 40.0f); field_mask = 0; - if (volume != DEFAULT_SOUND_PACKET_VOLUME) + if (nvolume != DEFAULT_SOUND_PACKET_VOLUME) field_mask |= SND_VOLUME; if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION) field_mask |= SND_ATTENUATION; @@ -835,7 +845,7 @@ void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float at MSG_WriteByte (&sv.datagram, svc_sound); MSG_WriteByte (&sv.datagram, field_mask); if (field_mask & SND_VOLUME) - MSG_WriteByte (&sv.datagram, volume); + MSG_WriteByte (&sv.datagram, nvolume); if (field_mask & SND_ATTENUATION) MSG_WriteByte (&sv.datagram, (int)(attenuation*64)); if (field_mask & SND_SPEEDUSHORT4000) @@ -914,7 +924,6 @@ void SV_SendServerinfo (client_t *client) { client->csqcentityscope[i] = 0; client->csqcentitysendflags[i] = 0xFFFFFF; - client->csqcentityglobalhistory[i] = 0; } for (i = 0;i < NUM_CSQCENTITYDB_FRAMES;i++) { @@ -930,17 +939,17 @@ void SV_SendServerinfo (client_t *client) 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]; - size_t i; + size_t j; // start a new demo file LHNETADDRESS_ToString(&(client->netconnection->peeraddress), ipaddress, sizeof(ipaddress), true); - for(i = 0; ipaddress[i]; ++i) - if(!isalnum(ipaddress[i])) - ipaddress[i] = '-'; + for(j = 0; ipaddress[j]; ++j) + if(!isalnum(ipaddress[j])) + ipaddress[j] = '-'; dpsnprintf (demofile, sizeof(demofile), "%s_%s_%d_%s.dem", Sys_TimeString (sv_autodemo_perclient_nameformat.string), sv.worldbasename, PRVM_NUM_FOR_EDICT(client->edict), ipaddress); SV_StartDemoRecording(client, demofile, -1); @@ -959,14 +968,14 @@ void SV_SendServerinfo (client_t *client) if(client->sv_demo_file != NULL) { - int i; + int k; static char buf[NET_MAXMESSAGE]; sizebuf_t sb; sb.data = (unsigned char *) buf; sb.maxsize = sizeof(buf); - i = 0; - while(MakeDownloadPacket(sv.csqc_progname, svs.csqc_progdata, sv.csqc_progsize, sv.csqc_progcrc, i++, &sb, sv.protocol)) + k = 0; + while(MakeDownloadPacket(sv.csqc_progname, svs.csqc_progdata, sv.csqc_progsize, sv.csqc_progcrc, k++, &sb, sv.protocol)) SV_WriteDemoMessage(client, &sb, false); } @@ -1082,12 +1091,14 @@ void SV_ConnectClient (int clientnum, netconn_t *netconnection) 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 : "-" ); } @@ -1105,9 +1116,6 @@ void SV_ConnectClient (int clientnum, netconn_t *netconnection) 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) @@ -1481,12 +1489,14 @@ static void SV_PrepareEntitiesForSending(void) #define MAX_LINEOFSIGHTTRACES 64 -qboolean SV_CanSeeBox(int numtraces, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs) +qboolean SV_CanSeeBox(int numtraces, vec_t eyejitter, vec_t enlarge, vec_t entboxexpand, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs) { prvm_prog_t *prog = SVVM_prog; float pitchsign; float alpha; float starttransformed[3], endtransformed[3]; + float boxminstransformed[3], boxmaxstransformed[3]; + float localboxcenter[3], localboxextents[3], localboxmins[3], localboxmaxs[3]; int blocked = 0; int traceindex; int originalnumtouchedicts; @@ -1496,27 +1506,35 @@ qboolean SV_CanSeeBox(int numtraces, vec_t enlarge, vec3_t eye, vec3_t entboxmin dp_model_t *model; prvm_edict_t *touch; static prvm_edict_t *touchedicts[MAX_EDICTS]; + vec3_t eyemins, eyemaxs, start; vec3_t boxmins, boxmaxs; vec3_t clipboxmins, clipboxmaxs; vec3_t endpoints[MAX_LINEOFSIGHTTRACES]; numtraces = min(numtraces, MAX_LINEOFSIGHTTRACES); + // jitter the eye location within this box + eyemins[0] = eye[0] - eyejitter; + eyemaxs[0] = eye[0] + eyejitter; + eyemins[1] = eye[1] - eyejitter; + eyemaxs[1] = eye[1] + eyejitter; + eyemins[2] = eye[2] - eyejitter; + eyemaxs[2] = eye[2] + eyejitter; // expand the box a little - boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0]; - boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0]; - boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1]; - boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1]; - boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2]; - boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2]; + boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0] - entboxexpand; + boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0] + entboxexpand; + boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1] - entboxexpand; + boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1] + entboxexpand; + boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2] - entboxexpand; + boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2] + entboxexpand; VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, endpoints[0]); for (traceindex = 1;traceindex < numtraces;traceindex++) VectorSet(endpoints[traceindex], lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2])); // calculate sweep box for the entire swarm of traces - VectorCopy(eye, clipboxmins); - VectorCopy(eye, clipboxmaxs); + VectorCopy(eyemins, clipboxmins); + VectorCopy(eyemaxs, clipboxmaxs); for (traceindex = 0;traceindex < numtraces;traceindex++) { clipboxmins[0] = min(clipboxmins[0], endpoints[traceindex][0]); @@ -1562,9 +1580,10 @@ qboolean SV_CanSeeBox(int numtraces, vec_t enlarge, vec3_t eye, vec3_t entboxmin for (traceindex = 0;traceindex < numtraces;traceindex++) { + VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2])); // check world occlusion if (sv.worldmodel && sv.worldmodel->brush.TraceLineOfSight) - if (!sv.worldmodel->brush.TraceLineOfSight(sv.worldmodel, eye, endpoints[traceindex])) + if (!sv.worldmodel->brush.TraceLineOfSight(sv.worldmodel, start, endpoints[traceindex], boxmins, boxmaxs)) continue; for (touchindex = 0;touchindex < numtouchedicts;touchindex++) { @@ -1577,9 +1596,22 @@ qboolean SV_CanSeeBox(int numtraces, vec_t enlarge, vec3_t eye, vec3_t entboxmin Matrix4x4_CreateFromQuakeEntity(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2], pitchsign * PRVM_serveredictvector(touch, angles)[0], PRVM_serveredictvector(touch, angles)[1], PRVM_serveredictvector(touch, angles)[2], 1); Matrix4x4_Invert_Simple(&imatrix, &matrix); // see if the ray hits this entity - Matrix4x4_Transform(&imatrix, eye, starttransformed); + Matrix4x4_Transform(&imatrix, start, starttransformed); Matrix4x4_Transform(&imatrix, endpoints[traceindex], endtransformed); - if (!model->brush.TraceLineOfSight(model, starttransformed, endtransformed)) + Matrix4x4_Transform(&imatrix, boxmins, boxminstransformed); + Matrix4x4_Transform(&imatrix, boxmaxs, boxmaxstransformed); + // transform the AABB to local space + VectorMAM(0.5f, boxminstransformed, 0.5f, boxmaxstransformed, localboxcenter); + localboxextents[0] = fabs(boxmaxstransformed[0] - localboxcenter[0]); + localboxextents[1] = fabs(boxmaxstransformed[1] - localboxcenter[1]); + localboxextents[2] = fabs(boxmaxstransformed[2] - localboxcenter[2]); + localboxmins[0] = localboxcenter[0] - localboxextents[0]; + localboxmins[1] = localboxcenter[1] - localboxextents[1]; + localboxmins[2] = localboxcenter[2] - localboxextents[2]; + localboxmaxs[0] = localboxcenter[0] + localboxextents[0]; + localboxmaxs[1] = localboxcenter[1] + localboxextents[1]; + localboxmaxs[2] = localboxcenter[2] + localboxextents[2]; + if (!model->brush.TraceLineOfSight(model, starttransformed, endtransformed, localboxmins, localboxmaxs)) { blocked++; break; @@ -1684,7 +1716,7 @@ static void SV_MarkWriteEntityStateToClient(entity_state_t *s) } // 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 @@ -1699,7 +1731,7 @@ static void SV_MarkWriteEntityStateToClient(entity_state_t *s) { int eyeindex; for (eyeindex = 0;eyeindex < sv.writeentitiestoclient_numeyes;eyeindex++) - if(SV_CanSeeBox(samples, enlarge, sv.writeentitiestoclient_eyes[eyeindex], ed->priv.server->cullmins, ed->priv.server->cullmaxs)) + if(SV_CanSeeBox(samples, sv_cullentities_trace_eyejitter.value, enlarge, sv_cullentities_trace_expand.value, sv.writeentitiestoclient_eyes[eyeindex], ed->priv.server->cullmins, ed->priv.server->cullmaxs)) break; if(eyeindex < sv.writeentitiestoclient_numeyes) svs.clients[sv.writeentitiestoclient_clientnumber].visibletime[s->number] = @@ -1782,7 +1814,7 @@ static void SV_AddCameraEyes(void) for(k = 0; k < sv.writeentitiestoclient_numeyes; ++k) if(eye_levels[k] <= MAX_EYE_RECURSION) { - if(SV_CanSeeBox(sv_cullentities_trace_samples.integer, sv_cullentities_trace_enlarge.value, sv.writeentitiestoclient_eyes[k], mi, ma)) + if(SV_CanSeeBox(sv_cullentities_trace_samples.integer, sv_cullentities_trace_eyejitter.value, sv_cullentities_trace_enlarge.value, sv_cullentities_trace_expand.value, sv.writeentitiestoclient_eyes[k], mi, ma)) { eye_levels[sv.writeentitiestoclient_numeyes] = eye_levels[k] + 1; VectorCopy(camera_origins[j], sv.writeentitiestoclient_eyes[sv.writeentitiestoclient_numeyes]); @@ -1843,7 +1875,7 @@ static void SV_WriteEntitiesToClient(client_t *client, prvm_edict_t *clent, size vec_t predtime = bound(0, host_client->ping, sv_cullentities_trace_prediction_time.value); vec3_t predeye; VectorMA(eye, predtime, PRVM_serveredictvector(camera, velocity), predeye); - if (SV_CanSeeBox(1, 0, eye, predeye, predeye)) + if (SV_CanSeeBox(1, 0, 0, 0, eye, predeye, predeye)) { VectorCopy(predeye, sv.writeentitiestoclient_eyes[sv.writeentitiestoclient_numeyes]); sv.writeentitiestoclient_numeyes++; @@ -2212,7 +2244,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t 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<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; } @@ -2427,7 +2478,7 @@ static void SV_SendClientDatagram (client_t *client) 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) } @@ -2458,7 +2509,9 @@ static void SV_UpdateToReliableMessages (void) 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)) { @@ -2488,7 +2541,9 @@ static void SV_UpdateToReliableMessages (void) 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 @@ -2496,7 +2551,9 @@ static void SV_UpdateToReliableMessages (void) 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] @@ -2517,7 +2574,7 @@ static void SV_UpdateToReliableMessages (void) // 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) @@ -2996,7 +3053,7 @@ int SV_ParticleEffectIndex(const char *name) { if (argc == 2) { - for (effectnameindex = 1;effectnameindex < SV_MAX_PARTICLEEFFECTNAME;effectnameindex++) + for (effectnameindex = 1;effectnameindex < MAX_PARTICLEEFFECTNAME;effectnameindex++) { if (sv.particleeffectname[effectnameindex][0]) { @@ -3010,7 +3067,7 @@ int SV_ParticleEffectIndex(const char *name) } } // 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; @@ -3022,7 +3079,7 @@ int SV_ParticleEffectIndex(const char *name) } } // 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 @@ -3056,7 +3113,7 @@ static void SV_CreateBaseline (void) int i, entnum, large; prvm_edict_t *svent; - // LordHavoc: clear *all* states (note just active ones) + // LordHavoc: clear *all* baselines (not just active ones) for (entnum = 0;entnum < prog->max_edicts;entnum++) { // get the current server version @@ -3328,6 +3385,8 @@ void SV_SpawnServer (const char *server) 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) { @@ -3463,12 +3522,15 @@ void SV_SpawnServer (const char *server) // 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(); @@ -3572,6 +3634,7 @@ static void SVVM_init_edict(prvm_prog_t *prog, prvm_edict_t *e) 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 @@ -3617,11 +3680,7 @@ static void SVVM_free_edict(prvm_prog_t *prog, prvm_edict_t *ed) 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) @@ -3854,7 +3913,7 @@ static void SV_VM_Setup(void) // PRVM_ED_FindGlobalOffset_FromStruct(globalvars_t, SetChangeParms); } else - Con_DPrintf("%s: %s system vars have been modified (CRC %i != engine %i), will not load in other engines", prog->name, sv_progs.string, prog->progs_crc, PROGHEADER_CRC); + Con_DPrintf("%s: %s system vars have been modified (CRC %i != engine %i), will not load in other engines\n", prog->name, sv_progs.string, prog->progs_crc, PROGHEADER_CRC); // OP_STATE is always supported on server because we add fields/globals for it prog->flag |= PRVM_OP_STATE;