DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
sv_user.c
Go to the documentation of this file.
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20// sv_user.c -- server code for moving users
21
22#include "quakedef.h"
23#include "sv_demo.h"
24#define DEBUGMOVES 0
25
28extern cvar_t sv_rollangle;
29extern cvar_t sv_rollspeed;
30
31/*
32==================
33SV_PreSpawn_f
34==================
35*/
37{
38 if (host_client->prespawned)
39 {
40 Con_Print("prespawn not valid -- already prespawned\n");
41 return;
42 }
43 host_client->prespawned = true;
44
45 if (host_client->netconnection)
46 {
47 SZ_Write (&host_client->netconnection->message, sv.signon.data, sv.signon.cursize);
48 MSG_WriteByte (&host_client->netconnection->message, svc_signonnum);
49 MSG_WriteByte (&host_client->netconnection->message, 2);
50 host_client->sendsignon = 0; // enable unlimited sends again
51 }
52
53 // reset the name change timer because the client will send name soon
54 host_client->nametime = 0;
55}
56
57/*
58==================
59SV_Spawn_f
60==================
61*/
63{
64 prvm_prog_t *prog = SVVM_prog;
65 int i;
66 client_t *client;
67 int stats[MAX_CL_STATS];
68
69 if (!host_client->prespawned)
70 {
71 Con_Print("Spawn not valid -- not yet prespawned\n");
72 return;
73 }
74 if (host_client->spawned)
75 {
76 Con_Print("Spawn not valid -- already spawned\n");
77 return;
78 }
79 host_client->spawned = true;
80
81 // reset name change timer again because they might want to change name
82 // again in the first 5 seconds after connecting
83 host_client->nametime = 0;
84
85 // LadyHavoc: moved this above the QC calls at FrikaC's request
86 // LadyHavoc: commented this out
87 //if (host_client->netconnection)
88 // SZ_Clear (&host_client->netconnection->message);
89
90 // run the entrance script
91 if (sv.loadgame)
92 {
93 // loaded games are fully initialized already
94 if (PRVM_serverfunction(RestoreGame))
95 {
96 Con_DPrint("Calling RestoreGame\n");
99 prog->ExecuteProgram(prog, PRVM_serverfunction(RestoreGame), "QC function RestoreGame is missing");
100 }
101 }
102 else
103 {
104 //Con_Printf("SV_Spawn_f: host_client->edict->netname = %s, host_client->edict->netname = %s, host_client->name = %s\n", PRVM_GetString(PRVM_serveredictstring(host_client->edict, netname)), PRVM_GetString(PRVM_serveredictstring(host_client->edict, netname)), host_client->name);
105
106 // copy spawn parms out of the client_t
107 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
108 (&PRVM_serverglobalfloat(parm1))[i] = host_client->spawn_parms[i];
109
110 // call the spawn function
111 host_client->clientconnectcalled = true;
114 prog->ExecuteProgram(prog, PRVM_serverfunction(ClientConnect), "QC function ClientConnect is missing");
115
116 Con_Printf("%s connected\n", host_client->name);
117
119 prog->ExecuteProgram(prog, PRVM_serverfunction(PutClientInServer), "QC function PutClientInServer is missing");
120 }
121
122 if (!host_client->netconnection)
123 return;
124
125 // send time of update
126 MSG_WriteByte (&host_client->netconnection->message, svc_time);
127 MSG_WriteFloat (&host_client->netconnection->message, sv.time);
128
129 // send all current names, colors, and frag counts
130 for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++)
131 {
132 if (!client->active)
133 continue;
134 MSG_WriteByte (&host_client->netconnection->message, svc_updatename);
135 MSG_WriteByte (&host_client->netconnection->message, i);
136 MSG_WriteString (&host_client->netconnection->message, client->name);
137 MSG_WriteByte (&host_client->netconnection->message, svc_updatefrags);
138 MSG_WriteByte (&host_client->netconnection->message, i);
139 MSG_WriteShort (&host_client->netconnection->message, client->frags);
140 MSG_WriteByte (&host_client->netconnection->message, svc_updatecolors);
141 MSG_WriteByte (&host_client->netconnection->message, i);
142 MSG_WriteByte (&host_client->netconnection->message, client->colors);
143 }
144
145 // send all current light styles
146 for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
147 {
148 if (sv.lightstyles[i][0])
149 {
150 MSG_WriteByte (&host_client->netconnection->message, svc_lightstyle);
151 MSG_WriteByte (&host_client->netconnection->message, (char)i);
152 MSG_WriteString (&host_client->netconnection->message, sv.lightstyles[i]);
153 }
154 }
155
156 // send some stats
157 MSG_WriteByte (&host_client->netconnection->message, svc_updatestat);
158 MSG_WriteByte (&host_client->netconnection->message, STAT_TOTALSECRETS);
159 MSG_WriteLong (&host_client->netconnection->message, (int)PRVM_serverglobalfloat(total_secrets));
160
161 MSG_WriteByte (&host_client->netconnection->message, svc_updatestat);
162 MSG_WriteByte (&host_client->netconnection->message, STAT_TOTALMONSTERS);
163 MSG_WriteLong (&host_client->netconnection->message, (int)PRVM_serverglobalfloat(total_monsters));
164
165 MSG_WriteByte (&host_client->netconnection->message, svc_updatestat);
166 MSG_WriteByte (&host_client->netconnection->message, STAT_SECRETS);
167 MSG_WriteLong (&host_client->netconnection->message, (int)PRVM_serverglobalfloat(found_secrets));
168
169 MSG_WriteByte (&host_client->netconnection->message, svc_updatestat);
170 MSG_WriteByte (&host_client->netconnection->message, STAT_MONSTERS);
171 MSG_WriteLong (&host_client->netconnection->message, (int)PRVM_serverglobalfloat(killed_monsters));
172
173 // send a fixangle
174 // Never send a roll angle, because savegames can catch the server
175 // in a state where it is expecting the client to correct the angle
176 // and it won't happen if the game was just loaded, so you wind up
177 // with a permanent head tilt
178 if (sv.loadgame)
179 {
180 MSG_WriteByte (&host_client->netconnection->message, svc_setangle);
181 MSG_WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, v_angle)[0], sv.protocol);
182 MSG_WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, v_angle)[1], sv.protocol);
183 MSG_WriteAngle (&host_client->netconnection->message, 0, sv.protocol);
184 }
185 else
186 {
187 MSG_WriteByte (&host_client->netconnection->message, svc_setangle);
188 MSG_WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, angles)[0], sv.protocol);
189 MSG_WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, angles)[1], sv.protocol);
190 MSG_WriteAngle (&host_client->netconnection->message, 0, sv.protocol);
191 }
192
193 SV_WriteClientdataToMessage (host_client, host_client->edict, &host_client->netconnection->message, stats);
194
195 MSG_WriteByte (&host_client->netconnection->message, svc_signonnum);
196 MSG_WriteByte (&host_client->netconnection->message, 3);
197}
198
199/*
200==================
201SV_Begin_f
202==================
203*/
205{
206 if (!host_client->spawned)
207 {
208 Con_Print("Begin not valid -- not yet spawned\n");
209 return;
210 }
211 if (host_client->begun)
212 {
213 Con_Print("Begin not valid -- already begun\n");
214 return;
215 }
216 host_client->begun = true;
217
218 // LadyHavoc: note: this code also exists in SV_DropClient
219 if (sv.loadgame)
220 {
221 int i;
222 for (i = 0;i < svs.maxclients;i++)
223 if (svs.clients[i].active && !svs.clients[i].spawned)
224 break;
225 if (i == svs.maxclients)
226 {
227 Con_Printf("Loaded game, everyone rejoined - unpausing\n");
228 sv.paused = sv.loadgame = false; // we're basically done with loading now
229 }
230 }
231}
232
233/*
234===============
235SV_SetIdealPitch
236===============
237*/
238#define MAX_FORWARD 6
240{
241 prvm_prog_t *prog = SVVM_prog;
242 float angleval, sinval, cosval, step, dir;
243 trace_t tr;
244 vec3_t top, bottom;
245 float z[MAX_FORWARD];
246 int i, j;
247 int steps;
248
249 if (!((int)PRVM_serveredictfloat(host_client->edict, flags) & FL_ONGROUND))
250 return;
251
252 angleval = PRVM_serveredictvector(host_client->edict, angles)[YAW] * M_PI*2 / 360;
253 sinval = sin(angleval);
254 cosval = cos(angleval);
255
256 for (i=0 ; i<MAX_FORWARD ; i++)
257 {
258 top[0] = PRVM_serveredictvector(host_client->edict, origin)[0] + cosval*(i+3)*12;
259 top[1] = PRVM_serveredictvector(host_client->edict, origin)[1] + sinval*(i+3)*12;
261
262 bottom[0] = top[0];
263 bottom[1] = top[1];
264 bottom[2] = top[2] - 160;
265
267 // if looking at a wall, leave ideal the way is was
268 if (tr.startsolid)
269 return;
270
271 // near a dropoff
272 if (tr.fraction == 1)
273 return;
274
275 z[i] = top[2] + tr.fraction*(bottom[2]-top[2]);
276 }
277
278 dir = 0;
279 steps = 0;
280 for (j=1 ; j<i ; j++)
281 {
282 step = z[j] - z[j-1];
283 if (step > -ON_EPSILON && step < ON_EPSILON)
284 continue;
285
286 // mixed changes
287 if (dir && ( step-dir > ON_EPSILON || step-dir < -ON_EPSILON ) )
288 return;
289
290 steps++;
291 dir = step;
292 }
293
294 if (!dir)
295 {
297 return;
298 }
299
300 if (steps < 2)
301 return;
303}
304
306static float wishspeed;
307
309
310/*
311==================
312SV_UserFriction
313
314==================
315*/
316static void SV_UserFriction (void)
317{
318 prvm_prog_t *prog = SVVM_prog;
319 float speed, newspeed, control, friction;
320 vec3_t start, stop;
321 trace_t trace;
322
324 if (!speed)
325 return;
326
327 // if the leading edge is over a dropoff, increase friction
328 start[0] = stop[0] = PRVM_serveredictvector(host_client->edict, origin)[0] + PRVM_serveredictvector(host_client->edict, velocity)[0]/speed*16;
329 start[1] = stop[1] = PRVM_serveredictvector(host_client->edict, origin)[1] + PRVM_serveredictvector(host_client->edict, velocity)[1]/speed*16;
331 stop[2] = start[2] - 34;
332
334
335 if (trace.fraction == 1.0)
337 else
338 friction = sv_friction.value;
339
340 // apply friction
341 control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed;
342 newspeed = speed - sv.frametime*control*friction;
343
344 if (newspeed < 0)
345 newspeed = 0;
346 else
347 newspeed /= speed;
348
350}
351
352/*
353==============
354SV_Accelerate
355==============
356*/
357static void SV_Accelerate (void)
358{
359 prvm_prog_t *prog = SVVM_prog;
360 int i;
361 float addspeed, accelspeed, currentspeed;
362
364 addspeed = wishspeed - currentspeed;
365 if (addspeed <= 0)
366 return;
367 accelspeed = sv_accelerate.value*sv.frametime*wishspeed;
368 if (accelspeed > addspeed)
369 accelspeed = addspeed;
370
371 for (i=0 ; i<3 ; i++)
372 PRVM_serveredictvector(host_client->edict, velocity)[i] += accelspeed*wishdir[i];
373}
374
376static void SV_AirAccelerate (vec3_t wishveloc)
377{
378 prvm_prog_t *prog = SVVM_prog;
379 int i;
380 float addspeed, wishspd, accelspeed, currentspeed;
381
382 wishspd = VectorNormalizeLength (wishveloc);
383 if (wishspd > sv_maxairspeed.value)
384 wishspd = sv_maxairspeed.value;
385 currentspeed = DotProduct (PRVM_serveredictvector(host_client->edict, velocity), wishveloc);
386 addspeed = wishspd - currentspeed;
387 if (addspeed <= 0)
388 return;
389 accelspeed = (sv_airaccelerate.value < 0 ? sv_accelerate.value : sv_airaccelerate.value)*(sv_gameplayfix_q2airaccelerate.integer ? wishspd : wishspeed) * sv.frametime;
390 if (accelspeed > addspeed)
391 accelspeed = addspeed;
392
393 for (i=0 ; i<3 ; i++)
394 PRVM_serveredictvector(host_client->edict, velocity)[i] += accelspeed*wishveloc[i];
395}
396
397
398static void DropPunchAngle (void)
399{
400 prvm_prog_t *prog = SVVM_prog;
401 vec_t len;
403
406
408 if (len > 0)
409 {
410 len -= 10*sv.frametime;
411 if (len < 0)
412 len = 0;
414 }
415
417 if (len > 0)
418 {
419 len -= 20*sv.frametime;
420 if (len < 0)
421 len = 0;
423 }
424
427}
428
429/*
430===================
431SV_WaterMove
432
433===================
434*/
435static void SV_WaterMove (void)
436{
437 prvm_prog_t *prog = SVVM_prog;
438 int i;
439 vec3_t wishvel, v_angle;
440 vec_t speed, newspeed, fwishspeed, addspeed, accelspeed, temp;
441
442 // user intentions
445
446 for (i=0 ; i<3 ; i++)
447 wishvel[i] = forward[i]*usercmd.forwardmove + right[i]*usercmd.sidemove;
448
449 if (!usercmd.forwardmove && !usercmd.sidemove && !usercmd.upmove)
450 wishvel[2] -= 60; // drift towards bottom
451 else
452 wishvel[2] += usercmd.upmove;
453
454 fwishspeed = VectorLength(wishvel);
455 if (fwishspeed > sv_maxspeed.value)
456 {
457 temp = sv_maxspeed.value/fwishspeed;
458 VectorScale (wishvel, temp, wishvel);
459 fwishspeed = sv_maxspeed.value;
460 }
461 fwishspeed *= 0.7;
462
463 // water friction
465 if (speed)
466 {
467 newspeed = speed - sv.frametime * speed * (sv_waterfriction.value < 0 ? sv_friction.value : sv_waterfriction.value);
468 if (newspeed < 0)
469 newspeed = 0;
470 temp = newspeed/speed;
472 }
473 else
474 newspeed = 0;
475
476 // water acceleration
477 if (!fwishspeed)
478 return;
479
480 addspeed = fwishspeed - newspeed;
481 if (addspeed <= 0)
482 return;
483
484 VectorNormalize (wishvel);
485 accelspeed = (sv_wateraccelerate.value < 0 ? sv_accelerate.value : sv_wateraccelerate.value) * fwishspeed * sv.frametime;
486 if (accelspeed > addspeed)
487 accelspeed = addspeed;
488
489 for (i=0 ; i<3 ; i++)
490 PRVM_serveredictvector(host_client->edict, velocity)[i] += accelspeed * wishvel[i];
491}
492
504
505
506/*
507===================
508SV_AirMove
509
510===================
511*/
512static void SV_AirMove (void)
513{
514 prvm_prog_t *prog = SVVM_prog;
515 int i;
516 vec3_t wishvel;
517 float fmove, smove, temp;
518
519 // LadyHavoc: correct quake movement speed bug when looking up/down
520 wishvel[0] = wishvel[2] = 0;
521 wishvel[1] = PRVM_serveredictvector(host_client->edict, angles)[1];
522 AngleVectors (wishvel, forward, right, up);
523
524 fmove = usercmd.forwardmove;
525 smove = usercmd.sidemove;
526
527// hack to not let you back into teleporter
528 if (sv.time < PRVM_serveredictfloat(host_client->edict, teleport_time) && fmove < 0)
529 fmove = 0;
530
531 for (i=0 ; i<3 ; i++)
532 wishvel[i] = forward[i]*fmove + right[i]*smove;
533
535 wishvel[2] += usercmd.upmove;
536
537 VectorCopy (wishvel, wishdir);
539 if (wishspeed > sv_maxspeed.value)
540 {
541 temp = sv_maxspeed.value/wishspeed;
542 VectorScale (wishvel, temp, wishvel);
543 wishspeed = sv_maxspeed.value;
544 }
545
547 {
548 // noclip
550 }
551 else if (onground)
552 {
554 SV_Accelerate ();
555 }
556 else
557 {
558 // not on ground, so little effect on velocity
559 SV_AirAccelerate (wishvel);
560 }
561}
562
563/*
564===================
565SV_PlayerPhysics
566
567the move fields specify an intended velocity in pix/sec
568the angle fields specify an exact angular motion in degrees
569===================
570*/
572{
573 prvm_prog_t *prog = SVVM_prog;
575
576 //Con_Printf("clientthink for %ims\n", (int) (sv.frametime * 1000));
577
579 // make sure the velocity is sane (not a NaN)
581
582 // LadyHavoc: QuakeC replacement for SV_PlayerPhysics (player movement)
584 {
587 prog->ExecuteProgram(prog, PRVM_serverfunction(SV_PlayerPhysics), "QC function SV_PlayerPhysics is missing");
589 return;
590 }
591
593 return;
594
596
598
599 // if dead, behave differently
600 if (PRVM_serveredictfloat(host_client->edict, health) <= 0)
601 return;
602
603 usercmd = host_client->cmd;
604
605 // angles
606 // show 1/3 the pitch angle and all the roll angle
612 {
615 }
616
618 {
619 SV_WaterJump ();
621 return;
622 }
623
624 // walk
626 {
627 SV_WaterMove ();
629 return;
630 }
631
632 SV_AirMove ();
634}
635
636/*
637===================
638SV_ReadClientMove
639===================
640*/
643static void SV_ReadClientMove (void)
644{
645 prvm_prog_t *prog = SVVM_prog;
646 int i;
647 usercmd_t newmove;
648 usercmd_t *move = &newmove;
649
650 memset(move, 0, sizeof(*move));
651
652 if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
653
654 // read ping time
655 if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3 && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5 && sv.protocol != PROTOCOL_DARKPLACES6)
657 move->time = MSG_ReadFloat(&sv_message);
658 if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
659 move->receivetime = (float)sv.time;
660
661#if DEBUGMOVES
662 Con_Printf("%s move%i #%u %ims (%ims) %i %i '%i %i %i' '%i %i %i'\n", move->time > move->receivetime ? "^3read future" : "^4read normal", sv_numreadmoves + 1, move->sequence, (int)floor((move->time - host_client->cmd.time) * 1000.0 + 0.5), (int)floor(move->time * 1000.0 + 0.5), move->impulse, move->buttons, (int)move->viewangles[0], (int)move->viewangles[1], (int)move->viewangles[2], (int)move->forwardmove, (int)move->sidemove, (int)move->upmove);
663#endif
664 // limit reported time to current time
665 // (incase the client is trying to cheat)
666 move->time = min(move->time, sv.time + sv.frametime);
667
668 // read current angles
669 for (i = 0;i < 3;i++)
670 {
671 if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
673 else if (sv.protocol == PROTOCOL_DARKPLACES1)
675 else if (sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3)
677 else
679 }
680 if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
681
682 // read movement
686 if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
687
688 // read buttons
689 // be sure to bitwise OR them into the move->buttons because we want to
690 // accumulate button presses from multiple packets per actual move
691 if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
693 else
695 if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
696
697 // read impulse
699 if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
700
701 // PRYDON_CLIENTCURSOR
702 if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3 && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5)
703 {
704 // 30 bytes
705 move->cursor_screen[0] = MSG_ReadShort(&sv_message) * (1.0f / 32767.0f);
706 move->cursor_screen[1] = MSG_ReadShort(&sv_message) * (1.0f / 32767.0f);
713 move->cursor_entitynumber = (unsigned short)MSG_ReadShort(&sv_message);
714 if (move->cursor_entitynumber >= prog->max_edicts)
715 {
716 Con_DPrintf("SV_ReadClientMessage: client send bad cursor_entitynumber\n");
717 move->cursor_entitynumber = 0;
718 }
719 // as requested by FrikaC, cursor_trace_ent is reset to world if the
720 // entity is free at time of receipt
721 if (PRVM_EDICT_NUM(move->cursor_entitynumber)->free)
722 move->cursor_entitynumber = 0;
723 if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
724 }
725
726 // if the previous move has not been applied yet, we need to accumulate
727 // the impulse/buttons from it
728 if (!host_client->cmd.applied)
729 {
730 if (!move->impulse)
731 move->impulse = host_client->cmd.impulse;
732 move->buttons |= host_client->cmd.buttons;
733 }
734
735 // now store this move for later execution
736 // (we have to buffer the moves because of old ones being repeated)
738 sv_readmoves[sv_numreadmoves++] = *move;
739
740 // movement packet loss tracking
741 // bones_was_here: checking begun prevents heavy loss detection right after a map change
742 if(move->sequence && host_client->begun)
743 {
744 if(move->sequence > host_client->movement_highestsequence_seen)
745 {
746 if(host_client->movement_highestsequence_seen)
747 {
748 // mark moves in between as lost
749 unsigned int delta = move->sequence - host_client->movement_highestsequence_seen - 1;
750 if(delta < NETGRAPH_PACKETS)
751 {
752 unsigned int u;
753 for(u = 0; u < delta; ++u)
754 host_client->movement_count[(host_client->movement_highestsequence_seen + 1 + u) % NETGRAPH_PACKETS] = -1;
755 }
756 else
757 memset(host_client->movement_count, -1, sizeof(host_client->movement_count));
758 }
759 // mark THIS move as seen for the first time
760 host_client->movement_count[move->sequence % NETGRAPH_PACKETS] = 1;
761 // update highest sequence seen
762 host_client->movement_highestsequence_seen = move->sequence;
763 }
764 else
765 if(host_client->movement_count[move->sequence % NETGRAPH_PACKETS] >= 0)
766 ++host_client->movement_count[move->sequence % NETGRAPH_PACKETS];
767 }
768 else
769 {
770 host_client->movement_highestsequence_seen = 0;
771 memset(host_client->movement_count, 0, sizeof(host_client->movement_count));
772 }
773}
774
775static void SV_ExecuteClientMoves(void)
776{
777 prvm_prog_t *prog = SVVM_prog;
778 int moveindex;
779 double moveframetime;
780 double oldframetime;
781 double oldframetime2;
782
783 if (sv_numreadmoves < 1)
784 return;
785 // only start accepting input once the player is spawned
786 if (!host_client->begun)
787 return;
788#if DEBUGMOVES
789 Con_Printf("SV_ExecuteClientMoves: read %i moves at sv.time %f\n", sv_numreadmoves, (float)sv.time);
790#endif
791 // disable clientside movement prediction in some cases
792 if (ceil(max(sv_readmoves[sv_numreadmoves-1].receivetime - sv_readmoves[sv_numreadmoves-1].time, 0) * 1000.0) < sv_clmovement_minping.integer)
793 host_client->clmovement_disabletimeout = host.realtime + sv_clmovement_minping_disabletime.value / 1000.0;
794 // several conditions govern whether clientside movement prediction is allowed
796 {
797 // process the moves in order and ignore old ones
798 // but always trust the latest move
799 // (this deals with bogus initial move sequences after level change,
800 // where the client will eventually catch up with the level change
801 // and reset its move sequence)
802 for (moveindex = 0;moveindex < sv_numreadmoves;moveindex++)
803 {
804 usercmd_t *move = sv_readmoves + moveindex;
805 if (host_client->movesequence < move->sequence || moveindex == sv_numreadmoves - 1)
806 {
807#if DEBUGMOVES
808 Con_Printf("%smove #%u %ims (%ims) %i %i '%i %i %i' '%i %i %i'\n", (move->time - host_client->cmd.time) > sv.frametime * 1.01 ? "^1" : "^2", move->sequence, (int)floor((move->time - host_client->cmd.time) * 1000.0 + 0.5), (int)floor(move->time * 1000.0 + 0.5), move->impulse, move->buttons, (int)move->viewangles[0], (int)move->viewangles[1], (int)move->viewangles[2], (int)move->forwardmove, (int)move->sidemove, (int)move->upmove);
809#endif
810 // this is a new move
811 move->time = bound(sv.time - 1, move->time, sv.time); // prevent slowhack/speedhack combos
812 move->time = max(move->time, host_client->cmd.time); // prevent backstepping of time
813 // bones_was_here: limit moveframetime to a multiple of sv.frametime to match inputtimeout behaviour
814 moveframetime = min(move->time - host_client->cmd.time, min(0.1, sys_ticrate.value > 0.0 && sv.frametime > 0.0 ? sv.frametime * ceil(sv_clmovement_inputtimeout.value / sv.frametime) : sv_clmovement_inputtimeout.value));
815
816
817 // discard (treat like lost) moves with too low distance from
818 // the previous one to prevent hacks using float inaccuracy
819 // clients will see this as packet loss in the netgraph
820 // this should also apply if a move cannot get
821 // executed because it came too late and
822 // already was performed serverside
823 if(moveframetime < 0.0005)
824 {
825 // count the move as LOST if we don't
826 // execute it but it has higher
827 // sequence count
828 if(host_client->movesequence)
829 if(move->sequence > host_client->movesequence)
830 host_client->movement_count[(move->sequence) % NETGRAPH_PACKETS] = -1;
831 continue;
832 }
833
834 //Con_Printf("movesequence = %i (%i lost), moveframetime = %f\n", move->sequence, move->sequence ? move->sequence - host_client->movesequence - 1 : 0, moveframetime);
835 host_client->cmd = *move;
836 host_client->movesequence = move->sequence;
837
838 // if using prediction, we need to perform moves when packets are
839 // received, even if multiple occur in one frame
840 // (they can't go beyond the current time so there is no cheat issue
841 // with this approach, and if they don't send input for a while they
842 // start moving anyway, so the longest 'lagaport' possible is
843 // determined by the sv_clmovement_inputtimeout cvar)
844 oldframetime = PRVM_serverglobalfloat(frametime);
845 oldframetime2 = sv.frametime;
846 // update ping time for qc to see while executing this move
847 host_client->ping = host_client->cmd.receivetime - host_client->cmd.time;
848 // the server and qc frametime values must be changed temporarily
849 PRVM_serverglobalfloat(frametime) = sv.frametime = moveframetime;
850 // if move is more than 50ms, split it into two moves (this matches QWSV behavior and the client prediction)
851 if (sv.frametime > 0.05)
852 {
853 PRVM_serverglobalfloat(frametime) = sv.frametime = moveframetime * 0.5f;
855 }
857 sv.frametime = oldframetime2;
858 PRVM_serverglobalfloat(frametime) = oldframetime;
859 host_client->clmovement_inputtimeout = min(0.1, sv_clmovement_inputtimeout.value);
860 }
861 }
862 }
863 else
864 {
865 // try to gather button bits from old moves, but only if their time is
866 // advancing (ones with the same timestamp can't be trusted)
867 for (moveindex = 0;moveindex < sv_numreadmoves-1;moveindex++)
868 {
869 usercmd_t *move = sv_readmoves + moveindex;
870 if (host_client->cmd.time < move->time)
871 {
872 sv_readmoves[sv_numreadmoves-1].buttons |= move->buttons;
873 if (move->impulse)
874 sv_readmoves[sv_numreadmoves-1].impulse = move->impulse;
875 }
876 }
877 // now copy the new move
879 host_client->cmd.time = max(host_client->cmd.time, sv.time);
880 // physics will run up to sv.time, so allow no predicted moves
881 // before that otherwise, there is a speedhack by turning
882 // prediction on and off repeatedly on client side because the
883 // engine would run BOTH client and server physics for the same
884 // time
885 host_client->movesequence = 0;
886 // make sure that normal physics takes over immediately
887 host_client->clmovement_inputtimeout = 0;
888 // update ping time
889 host_client->ping = host_client->cmd.receivetime - sv_readmoves[sv_numreadmoves-1].time;
890 }
891}
892
894{
895 prvm_prog_t *prog = SVVM_prog;
896 usercmd_t *move = &host_client->cmd;
897 int j, movementloss, packetloss;
898
899 if (!move->receivetime)
900 return;
901
902 // note: a move can be applied multiple times if the client packets are
903 // not coming as often as the physics is executed, and the move must be
904 // applied before running qc each time because the id1 qc had a bug where
905 // it clears self.button2 in PlayerJump, causing pogostick behavior if
906 // moves are not applied every time before calling qc
907 move->applied = true;
908
909 // set the edict fields
911 PRVM_serveredictfloat(host_client->edict, button2) = (move->buttons & 2)>>1;
912 if (move->impulse)
914 // only send the impulse to qc once
915 move->impulse = 0;
916
917 movementloss = packetloss = 0;
918 if(host_client->netconnection)
919 {
920 for (j = 0;j < NETGRAPH_PACKETS;j++)
921 if (host_client->netconnection->incoming_netgraph[j].unreliablebytes == NETGRAPH_LOSTPACKET)
922 packetloss++;
923 for (j = 0;j < NETGRAPH_PACKETS;j++)
924 if (host_client->movement_count[j] < 0)
925 movementloss++;
926 }
927
929 PRVM_serveredictfloat(host_client->edict, button3) = ((move->buttons >> 2) & 1);
930 PRVM_serveredictfloat(host_client->edict, button4) = ((move->buttons >> 3) & 1);
931 PRVM_serveredictfloat(host_client->edict, button5) = ((move->buttons >> 4) & 1);
932 PRVM_serveredictfloat(host_client->edict, button6) = ((move->buttons >> 5) & 1);
933 PRVM_serveredictfloat(host_client->edict, button7) = ((move->buttons >> 6) & 1);
934 PRVM_serveredictfloat(host_client->edict, button8) = ((move->buttons >> 7) & 1);
935 PRVM_serveredictfloat(host_client->edict, button9) = ((move->buttons >> 11) & 1);
936 PRVM_serveredictfloat(host_client->edict, button10) = ((move->buttons >> 12) & 1);
937 PRVM_serveredictfloat(host_client->edict, button11) = ((move->buttons >> 13) & 1);
938 PRVM_serveredictfloat(host_client->edict, button12) = ((move->buttons >> 14) & 1);
939 PRVM_serveredictfloat(host_client->edict, button13) = ((move->buttons >> 15) & 1);
940 PRVM_serveredictfloat(host_client->edict, button14) = ((move->buttons >> 16) & 1);
941 PRVM_serveredictfloat(host_client->edict, button15) = ((move->buttons >> 17) & 1);
942 PRVM_serveredictfloat(host_client->edict, button16) = ((move->buttons >> 18) & 1);
943 PRVM_serveredictfloat(host_client->edict, buttonuse) = ((move->buttons >> 8) & 1);
944 PRVM_serveredictfloat(host_client->edict, buttonchat) = ((move->buttons >> 9) & 1);
945 PRVM_serveredictfloat(host_client->edict, cursor_active) = ((move->buttons >> 10) & 1);
951 PRVM_serveredictfloat(host_client->edict, ping) = host_client->ping * 1000.0;
954}
955
956static qbool SV_FrameLost(int framenum)
957{
958 if (host_client->entitydatabase5)
959 {
960 if (framenum <= host_client->entitydatabase5->latestframenum)
961 {
962 EntityFrame5_LostFrame(host_client->entitydatabase5, framenum);
964 return true;
965 }
966 }
967 return false;
968}
969
970static void SV_FrameAck(int framenum)
971{
972 if (host_client->entitydatabase)
973 EntityFrame_AckFrame(host_client->entitydatabase, framenum);
974 else if (host_client->entitydatabase4)
975 EntityFrame4_AckFrame(host_client->entitydatabase4, framenum, true);
976 else if (host_client->entitydatabase5)
977 EntityFrame5_AckFrame(host_client->entitydatabase5, framenum);
978}
979
980/*
981===================
982SV_ReadClientMessage
983===================
984*/
986{
987 prvm_prog_t *prog = SVVM_prog;
988 int netcmd, num, start;
989 char *s, *p, *q;
990 size_t slen;
991
992 if(sv_autodemo_perclient.integer >= 2)
993 SV_WriteDemoMessage(host_client, &(host_client->netconnection->message), true);
994
995 //MSG_BeginReading ();
996 sv_numreadmoves = 0;
997
998 for(;;)
999 {
1000 if (!host_client->active)
1001 {
1002 // a command caused an error
1003 SV_DropClient (false, "Connection closing");
1004 return;
1005 }
1006
1007 if (sv_message.badread)
1008 {
1009 Con_Print("SV_ReadClientMessage: badread\n");
1010 SV_DropClient (false, "An internal server error occurred");
1011 return;
1012 }
1013
1014 netcmd = MSG_ReadByte(&sv_message);
1015 if (netcmd == -1)
1016 {
1017 // end of message
1018 // apply the moves that were read this frame
1020 break;
1021 }
1022
1023 switch (netcmd)
1024 {
1025 default:
1026 Con_Printf("SV_ReadClientMessage: unknown command char %i (at offset 0x%x)\n", netcmd, sv_message.readcount);
1027 if (developer_networking.integer)
1029 SV_DropClient (false, "Unknown message sent to the server");
1030 return;
1031
1032 case clc_nop:
1033 break;
1034
1035 case clc_stringcmd:
1036 // allow reliable messages now as the client is done with initial loading
1037 if (host_client->sendsignon == 2)
1038 host_client->sendsignon = 0;
1040 s = sv_readstring;
1041 q = NULL;
1042 for(p = s; *p; ++p) switch(*p)
1043 {
1044 case 10:
1045 case 13:
1046 if(!q)
1047 q = p;
1048 break;
1049 default:
1050 if(q)
1051 goto clc_stringcmd_invalid; // newline seen, THEN something else -> possible exploit
1052 break;
1053 }
1054 if(q)
1055 *q = 0;
1056 if (strncasecmp(s, "spawn", 5) == 0
1057 || strncasecmp(s, "begin", 5) == 0
1058 || strncasecmp(s, "prespawn", 8) == 0)
1060 else if (PRVM_serverfunction(SV_ParseClientCommand))
1061 {
1062 int restorevm_tempstringsbuf_cursize;
1063 restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
1064 PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, s, slen);
1067 prog->ExecuteProgram(prog, PRVM_serverfunction(SV_ParseClientCommand), "QC function SV_ParseClientCommand is missing");
1068 prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
1069 }
1070 else
1072 break;
1073
1074clc_stringcmd_invalid:
1075 Con_Printf("Received invalid stringcmd from %s\n", host_client->name);
1076 if(developer.integer > 0)
1077 Com_HexDumpToConsole((unsigned char *) s, (int)strlen(s));
1078 break;
1079
1080 case clc_disconnect:
1081 SV_DropClient (true, sv.protocol == PROTOCOL_DARKPLACES8
1083 : "Disconnect by user"); // client wants to disconnect
1084 return;
1085
1086 case clc_move:
1088 break;
1089
1091 start = MSG_ReadLong(&sv_message);
1092 num = MSG_ReadShort(&sv_message);
1093 if (host_client->download_file && host_client->download_started)
1094 {
1095 if (host_client->download_expectedposition == start)
1096 {
1097 int size = (int)FS_FileSize(host_client->download_file);
1098 // a data block was successfully received by the client,
1099 // update the expected position on the next data block
1100 host_client->download_expectedposition = start + num;
1101 // if this was the last data block of the file, it's done
1102 if (host_client->download_expectedposition >= FS_FileSize(host_client->download_file))
1103 {
1104 // tell the client that the download finished
1105 // we need to calculate the crc now
1106 //
1107 // note: at this point the OS probably has the file
1108 // entirely in memory, so this is a faster operation
1109 // now than it was when the download started.
1110 //
1111 // it is also preferable to do this at the end of the
1112 // download rather than the start because it reduces
1113 // potential for Denial Of Service attacks against the
1114 // server.
1115 int crc;
1116 unsigned char *temp;
1117 FS_Seek(host_client->download_file, 0, SEEK_SET);
1118 temp = (unsigned char *) Mem_Alloc(tempmempool, size);
1119 FS_Read(host_client->download_file, temp, size);
1120 crc = CRC_Block(temp, size);
1121 Mem_Free(temp);
1122 // calculated crc, send the file info to the client
1123 // (so that it can verify the data)
1124 SV_ClientCommands("\ncl_downloadfinished %i %i %s\n", size, crc, host_client->download_name);
1125 Con_DPrintf("Download of %s by %s has finished\n", host_client->download_name, host_client->name);
1126 FS_Close(host_client->download_file);
1127 host_client->download_file = NULL;
1128 host_client->download_name[0] = 0;
1129 host_client->download_expectedposition = 0;
1130 host_client->download_started = false;
1131 }
1132 }
1133 else
1134 {
1135 // a data block was lost, reset to the expected position
1136 // and resume sending from there
1137 FS_Seek(host_client->download_file, host_client->download_expectedposition, SEEK_SET);
1138 }
1139 }
1140 break;
1141
1142 case clc_ackframe:
1143 if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
1144 num = MSG_ReadLong(&sv_message);
1145 if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
1146 if (developer_networkentities.integer >= 10)
1147 Con_Printf("recv clc_ackframe %i\n", num);
1148 // if the client hasn't progressed through signons yet,
1149 // ignore any clc_ackframes we get (they're probably from the
1150 // previous level)
1151 if (host_client->begun && host_client->latestframenum < num)
1152 {
1153 int i;
1154 for (i = host_client->latestframenum + 1;i < num;i++)
1155 if (!SV_FrameLost(i))
1156 break;
1157 SV_FrameAck(num);
1158 host_client->latestframenum = num;
1159 }
1160 break;
1161 }
1162 }
1163}
1164
#define SUPERCONTENTS_SOLID
Definition bspfile.h:196
cvar_t developer_networkentities
Definition cl_parse.c:173
void Cmd_ExecuteString(cmd_state_t *cmd, const char *text, size_t textlen, cmd_source_t src, qbool lockmutex)
Parses a single line of text into arguments and tries to execute it.
Definition cmd.c:2068
cmd_state_t * cmd_serverfromclient
command interpreter for server commands received over network from clients uses cmddefs_null
Definition cmd.c:26
@ src_client
came in over a net connection as a clc_stringcmd host_client will be valid during this state.
Definition cmd.h:73
cvar_t collision_extendmovelength
Definition collision.c:14
unsigned short CRC_Block(const unsigned char *data, size_t size)
Definition com_crc16.c:75
int EntityFrame4_AckFrame(entityframe4_database_t *d, int framenum, int servermode)
Definition com_ents4.c:74
void EntityFrame_AckFrame(entityframe_database_t *d, int frame)
Definition com_ents.c:35
char * MSG_ReadString(sizebuf_t *sb, char *string, size_t maxstring)
Definition com_msg.c:341
void MSG_WriteShort(sizebuf_t *sb, int c)
Definition com_msg.c:138
float MSG_ReadAngle32f(sizebuf_t *sb)
Definition com_msg.c:419
void MSG_WriteString(sizebuf_t *sb, const char *s)
Definition com_msg.c:173
void MSG_WriteLong(sizebuf_t *sb, int c)
Definition com_msg.c:147
float MSG_ReadAngle8i(sizebuf_t *sb)
Definition com_msg.c:409
float MSG_ReadAngle16i(sizebuf_t *sb)
Definition com_msg.c:414
void MSG_WriteByte(sizebuf_t *sb, int c)
Definition com_msg.c:130
void MSG_WriteFloat(sizebuf_t *sb, float f)
Definition com_msg.c:158
void MSG_WriteAngle(sizebuf_t *sb, float f, protocolversion_t protocol)
Definition com_msg.c:237
float MSG_ReadCoord16i(sizebuf_t *sb)
Definition com_msg.c:379
size_t MSG_ReadString_len(sizebuf_t *sb, char *string, size_t maxstring)
Same as MSG_ReadString except it returns the number of bytes written to *string excluding the \0 term...
Definition com_msg.c:352
float Com_CalcRoll(const vec3_t angles, const vec3_t velocity, const vec_t angleval, const vec_t velocityval)
Definition common.c:890
void Com_HexDumpToConsole(const unsigned char *data, int size)
Definition common.c:82
void SZ_Write(sizebuf_t *buf, const unsigned char *data, int length)
Definition common.c:72
#define MSG_ReadShort
Definition common.h:191
#define MSG_ReadFloat
Definition common.h:193
@ PROTOCOL_DARKPLACES2
various changes
Definition common.h:140
@ PROTOCOL_DARKPLACES4
various changes
Definition common.h:138
@ PROTOCOL_NEHAHRABJP2
same as NEHAHRABJP but with 16bit soundindex
Definition common.h:147
@ PROTOCOL_DARKPLACES3
uses EntityFrame4 entity snapshot encoder/decoder which is broken, this attempted to do partial snaps...
Definition common.h:139
@ PROTOCOL_NEHAHRABJP
same as QUAKEDP but with 16bit modelindex
Definition common.h:146
@ PROTOCOL_DARKPLACES5
uses EntityFrame5 entity snapshot encoder/decoder which is based on a Tribes networking article at ht...
Definition common.h:137
@ PROTOCOL_QUAKEDP
darkplaces extended quake protocol (used by TomazQuake and others), backwards compatible as long as n...
Definition common.h:142
@ PROTOCOL_DARKPLACES6
various changes
Definition common.h:136
@ PROTOCOL_QUAKE
quake (aka netquake/normalquake/nq) protocol
Definition common.h:144
@ PROTOCOL_DARKPLACES8
added parting messages. WIP
Definition common.h:134
@ PROTOCOL_NEHAHRABJP3
same as NEHAHRABJP2 but with some changes
Definition common.h:148
@ PROTOCOL_NEHAHRAMOVIE
Nehahra movie protocol, a big nasty hack dating back to early days of the Quake Standards Group (but ...
Definition common.h:143
@ PROTOCOL_DARKPLACES1
uses EntityFrame entity snapshot encoder/decoder which is a QuakeWorld-like entity snapshot delta com...
Definition common.h:141
#define MSG_ReadLong
Definition common.h:192
#define MSG_ReadByte(sb)
Definition common.h:188
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
void Con_DPrint(const char *msg)
A Con_Print that only shows up if the "developer" cvar is set.
Definition console.c:1531
vector size
float movetype
float flags
entity self
float frametime
vector mins
vector velocity
float time
vector angles
vector origin
float disableclientprediction
float button10
float button12
float button3
float button7
float button11
float ping
float button16
float ping_movementloss
vector movement
float ping_packetloss
float button4
vector cursor_screen
float button6
float friction
entity cursor_trace_ent
float idealpitch
float button8
float cursor_active
float buttonchat
float buttonuse
float button9
float button15
float button13
vector punchvector
float button14
vector cursor_trace_start
float button5
vector cursor_trace_endpos
fs_offset_t FS_Read(qfile_t *file, void *buffer, size_t buffersize)
Definition fs.c:3067
int FS_Seek(qfile_t *file, fs_offset_t offset, int whence)
Definition fs.c:3360
static int(ZEXPORT *qz_inflate)(z_stream *strm
fs_offset_t FS_FileSize(qfile_t *file)
Definition fs.c:3475
int FS_Close(qfile_t *file)
Definition fs.c:2971
GLubyte GLubyte GLubyte z
Definition glquake.h:782
cvar_t developer
Definition host.c:48
host_static_t host
Definition host.c:41
float VectorNormalizeLength(vec3_t v)
returns vector length
Definition mathlib.c:763
void AngleVectors(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition mathlib.c:444
#define max(A, B)
Definition mathlib.h:38
#define min(A, B)
Definition mathlib.h:37
#define VectorNormalize(v)
Definition mathlib.h:104
#define bound(min, num, max)
Definition mathlib.h:34
#define VectorLength(a)
Definition mathlib.h:109
#define VectorSet(vec, x, y, z)
Definition mathlib.h:96
#define DotProduct(a, b)
Definition mathlib.h:98
#define VectorCopy(in, out)
Definition mathlib.h:101
#define VectorScale(in, scale, out)
Definition mathlib.h:111
#define VectorAdd(a, b, out)
Definition mathlib.h:100
#define M_PI
Definition mathlib.h:28
#define Vector2Length(a)
Definition mathlib.h:79
float ceil(float f)
float strlen(string s)
float cos(float f)
void cmd(string command,...)
float sin(float f)
float floor(float f)
char sv_readstring[MAX_INPUTLINE]
Definition netconn.c:76
cvar_t developer_networking
Definition netconn.c:89
sizebuf_t sv_message
Definition netconn.c:72
#define NETGRAPH_PACKETS
Definition netconn.h:222
#define NETGRAPH_LOSTPACKET
Definition netconn.h:224
#define OFS_PARM0
Definition pr_comp.h:34
float parm1
Definition progsdefs.qc:45
float button2
Definition progsdefs.qc:156
float killed_monsters
Definition progsdefs.qc:40
vector punchangle
Definition progsdefs.qc:117
float button0
Definition progsdefs.qc:154
float total_secrets
Definition progsdefs.qc:36
vector v_angle
Definition progsdefs.qc:161
float teleport_time
Definition progsdefs.qc:176
vector view_ofs
Definition progsdefs.qc:151
float health
Definition progsdefs.qc:137
float waterlevel
Definition progsdefs.qc:181
float fixangle
Definition progsdefs.qc:160
vector movedir
Definition progsdefs.qc:203
float total_monsters
Definition progsdefs.qc:37
float impulse
Definition progsdefs.qc:158
float found_secrets
Definition progsdefs.qc:39
#define PRVM_serveredictvector(ed, fieldname)
Definition progsvm.h:173
int PRVM_SetTempString(prvm_prog_t *prog, const char *s, size_t slen)
Takes an strlen (not a buffer size).
#define PRVM_serverglobaledict(fieldname)
Definition progsvm.h:180
#define PRVM_serveredictedict(ed, fieldname)
Definition progsvm.h:175
#define PRVM_EDICT_TO_PROG(e)
Definition progsvm.h:875
#define PRVM_EDICT_NUM(n)
Definition progsvm.h:867
#define PRVM_serverglobalfloat(fieldname)
Definition progsvm.h:177
#define PRVM_serveredictfloat(ed, fieldname)
Definition progsvm.h:172
#define PRVM_serverfunction(funcname)
Definition progsvm.h:182
#define SVVM_prog
Definition progsvm.h:766
#define PRVM_G_INT(o)
Definition progsvm.h:883
#define clc_nop
Definition protocol.h:288
#define svc_updatefrags
Definition protocol.h:233
#define clc_move
Definition protocol.h:290
#define clc_ackdownloaddata
Definition protocol.h:295
void EntityFrameCSQC_LostFrame(struct client_s *client, int framenum)
#define svc_signonnum
Definition protocol.h:247
#define svc_setangle
Definition protocol.h:225
#define svc_updatestat
Definition protocol.h:217
#define clc_ackframe
Definition protocol.h:294
#define svc_time
Definition protocol.h:221
#define svc_lightstyle
Definition protocol.h:231
void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum)
Definition sv_ents5.c:684
#define svc_updatecolors
Definition protocol.h:236
void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum)
Definition sv_ents5.c:623
#define clc_stringcmd
Definition protocol.h:291
#define clc_disconnect
Definition protocol.h:289
#define svc_updatename
Definition protocol.h:232
#define ON_EPSILON
point on plane side epsilon
Definition qdefs.h:178
#define MAX_LIGHTSTYLES
max flickering light styles in level (note: affects savegame format)
Definition qdefs.h:108
#define CL_MAX_USERCMDS
max number of predicted input packets in queue
Definition qdefs.h:115
#define STAT_TOTALMONSTERS
Definition qstats.h:20
#define STAT_MONSTERS
bumped by svc_killedmonster
Definition qstats.h:22
#define STAT_SECRETS
bumped on client side by svc_foundsecret
Definition qstats.h:21
#define STAT_TOTALSECRETS
Definition qstats.h:19
#define MAX_CL_STATS
Definition qstats.h:7
#define NULL
Definition qtypes.h:12
float vec_t
Definition qtypes.h:68
vec_t vec3_t[3]
Definition qtypes.h:71
bool qbool
Definition qtypes.h:9
#define YAW
Definition qtypes.h:19
#define PITCH
Definition qtypes.h:16
#define ROLL
Definition qtypes.h:22
#define FL_WATERJUMP
player jumping out of water
Definition server.h:368
void SV_PlayerPhysics(void)
Definition sv_user.c:571
cvar_t sv_waterfriction
Definition sv_main.c:157
server_t sv
local server
Definition sv_main.c:223
#define NUM_SPAWN_PARMS
Definition server.h:180
#define MOVETYPE_NOCLIP
Definition server.h:320
cvar_t sv_maxairspeed
Definition sv_main.c:140
cvar_t sv_clmovement_enable
Definition sv_main.c:77
#define MOVETYPE_WALK
gravity
Definition server.h:315
cvar_t sv_wateraccelerate
Definition sv_main.c:156
#define MOVETYPE_NONE
never moves
Definition server.h:312
void SV_WriteClientdataToMessage(client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
Definition sv_send.c:1091
trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend)
Definition sv_phys.c:256
cvar_t sys_ticrate
Definition sv_main.c:166
cvar_t sv_maxspeed
Definition sv_main.c:142
void SV_CheckVelocity(prvm_edict_t *ent)
Definition sv_phys.c:965
cvar_t sv_gameplayfix_q2airaccelerate
Definition sv_main.c:119
cvar_t sv_idealpitchscale
Definition sv_main.c:136
void SV_DropClient(qbool leaving, const char *reason,...)
Definition sv_main.c:1018
cvar_t sv_edgefriction
Definition sv_main.c:100
int SV_GenericHitSuperContentsMask(const prvm_edict_t *edict)
calculates hitsupercontentsmask for a generic qc entity
Definition sv_phys.c:73
server_static_t svs
persistant server info
Definition sv_main.c:224
cvar_t sv_clmovement_inputtimeout
Definition sv_main.c:80
cvar_t sv_friction
Definition sv_main.c:103
#define FL_ONGROUND
Definition server.h:366
cvar_t sv_clmovement_minping
Definition sv_main.c:78
cvar_t sv_stopspeed
Definition sv_main.c:154
cvar_t sv_clmovement_minping_disabletime
Definition sv_main.c:79
void SV_ClientCommands(const char *fmt,...) DP_FUNC_PRINTF(1)
Definition sv_send.c:135
client_t * host_client
Definition sv_main.c:29
cvar_t sv_airaccelerate
Definition sv_main.c:60
cvar_t sv_accelerate
Definition sv_main.c:55
cvar_t sv_playerphysicsqc
Definition sv_main.c:145
void SV_Physics_ClientMove(void)
Definition sv_phys.c:2810
vec2 dir
precision highp float
Definition shader_glsl.h:53
qbool active
false = empty client slot
Definition server.h:185
int colors
Definition server.h:236
int frags
Definition server.h:237
char name[MAX_SCOREBOARDNAME]
Definition server.h:235
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
Definition cmd.h:127
Definition cvar.h:66
int max_edicts
number of edicts for which space has been (should be) allocated
Definition progsvm.h:673
void(* ExecuteProgram)(struct prvm_prog_s *prog, func_t fnum, const char *errormessage)
pointer to one of the *VM_ExecuteProgram functions
Definition progsvm.h:749
sizebuf_t tempstringsbuf
buffer for storing all tempstrings created during one invocation of ExecuteProgram
Definition progsvm.h:644
int cursize
Definition common.h:54
double fraction
Definition collision.h:40
qbool startsolid
Definition collision.h:26
int impulse
Definition protocol.h:396
float receivetime
Definition protocol.h:393
vec3_t cursor_start
Definition protocol.h:385
qbool applied
Definition protocol.h:398
vec3_t viewangles
Definition protocol.h:377
vec3_t cursor_screen
Definition protocol.h:384
int cursor_entitynumber
Definition protocol.h:390
vec3_t cursor_impact
Definition protocol.h:387
double time
Definition protocol.h:392
float forwardmove
Definition protocol.h:380
int buttons
Definition protocol.h:395
float upmove
Definition protocol.h:382
unsigned int sequence
Definition protocol.h:397
float sidemove
Definition protocol.h:381
void SV_WriteDemoMessage(client_t *client, sizebuf_t *sendbuffer, qbool clienttoserver)
Definition sv_demo.c:32
cvar_t sv_rollangle
Definition sv_main.c:176
cvar_t sv_rollspeed
Definition sv_main.c:175
cvar_t sv_autodemo_perclient
Definition sv_main.c:211
static vec3_t wishdir
Definition sv_user.c:305
static void DropPunchAngle(void)
Definition sv_user.c:398
void SV_PlayerPhysics(void)
Definition sv_user.c:571
static float wishspeed
Definition sv_user.c:306
void SV_Begin_f(cmd_state_t *cmd)
Definition sv_user.c:204
void SV_ReadClientMessage(void)
Definition sv_user.c:985
void SV_ApplyClientMove(void)
Definition sv_user.c:893
int sv_numreadmoves
Definition sv_user.c:641
static void SV_WaterJump(void)
Definition sv_user.c:493
void SV_Spawn_f(cmd_state_t *cmd)
Definition sv_user.c:62
static usercmd_t usercmd
Definition sv_user.c:26
static void SV_AirAccelerate(vec3_t wishveloc)
Definition sv_user.c:376
void SV_SetIdealPitch(void)
Definition sv_user.c:239
static void SV_ExecuteClientMoves(void)
Definition sv_user.c:775
static qbool onground
Definition sv_user.c:308
static vec3_t forward
Definition sv_user.c:305
static void SV_ReadClientMove(void)
Definition sv_user.c:643
static void SV_UserFriction(void)
Definition sv_user.c:316
static vec3_t right
Definition sv_user.c:305
static void SV_Accelerate(void)
Definition sv_user.c:357
usercmd_t sv_readmoves[CL_MAX_USERCMDS]
Definition sv_user.c:642
static void SV_FrameAck(int framenum)
Definition sv_user.c:970
static void SV_WaterMove(void)
Definition sv_user.c:435
static qbool SV_FrameLost(int framenum)
Definition sv_user.c:956
static vec3_t up
Definition sv_user.c:305
void SV_PreSpawn_f(cmd_state_t *cmd)
Definition sv_user.c:36
static void SV_AirMove(void)
Definition sv_user.c:512
#define MAX_FORWARD
Definition sv_user.c:238
#define MOVE_NOMONSTERS
Definition world.h:29
mempool_t * tempmempool
Definition zone.c:794
#define Mem_Free(mem)
Definition zone.h:96
#define Mem_Alloc(pool, size)
Definition zone.h:92