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{
39 {
40 Con_Print("prespawn not valid -- already prespawned\n");
41 return;
42 }
43 host_client->prespawned = true;
44
46 {
50 host_client->sendsignon = 0; // enable unlimited sends again
51 }
52
53 // reset the name change timer because the client will send name soon
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
70 {
71 Con_Print("Spawn not valid -- not yet prespawned\n");
72 return;
73 }
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
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++)
109
110 // call the spawn function
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
123 return;
124
125 // send time of update
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;
143 }
144
145 // send all current light styles
146 for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
147 {
148 if (sv.lightstyles[i][0])
149 {
153 }
154 }
155
156 // send some stats
160
164
168
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 {
184 }
185 else
186 {
191 }
192
194
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
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
331 stop[2] = start[2] - 34;
332
334
335 if (trace.fraction == 1.0)
337 else
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;
368 if (accelspeed > addspeed)
369 accelspeed = addspeed;
370
371 for (i=0 ; i<3 ; 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;
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++)
448
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;
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
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);
540 {
542 VectorScale (wishvel, temp, wishvel);
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
601 return;
602
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
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 {
673 else if (sv.protocol == PROTOCOL_DARKPLACES1)
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
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
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)
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 {
745 {
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)
755 }
756 else
758 }
759 // mark THIS move as seen for the first time
761 // update highest sequence seen
763 }
764 else
767 }
768 else
769 {
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
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
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
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;
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
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;
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 {
873 if (move->impulse)
875 }
876 }
877 // now copy the new move
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
886 // make sure that normal physics takes over immediately
888 // update ping 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
912 if (move->impulse)
914 // only send the impulse to qc once
915 move->impulse = 0;
916
917 movementloss = packetloss = 0;
919 {
920 for (j = 0;j < NETGRAPH_PACKETS;j++)
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);
954}
955
956static qbool SV_FrameLost(int framenum)
957{
959 {
960 if (framenum <= host_client->entitydatabase5->latestframenum)
961 {
964 return true;
965 }
966 }
967 return false;
968}
969
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
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);
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)
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:
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);
1094 {
1096 {
1098 // a data block was successfully received by the client,
1099 // update the expected position on the next data block
1101 // if this was the last data block of the file, it's done
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);
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);
1128 host_client->download_name[0] = 0;
1131 }
1132 }
1133 else
1134 {
1135 // a data block was lost, reset to the expected position
1136 // and resume sending from there
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__);
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)
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);
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:3066
int FS_Seek(qfile_t *file, fs_offset_t offset, int whence)
Definition fs.c:3359
static int(ZEXPORT *qz_inflate)(z_stream *strm
fs_offset_t FS_FileSize(qfile_t *file)
Definition fs.c:3474
int FS_Close(qfile_t *file)
Definition fs.c:2970
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
int i
#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
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_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
float clmovement_inputtimeout
this is used by sv_clmovement_inputtimeout code
Definition server.h:229
qbool active
false = empty client slot
Definition server.h:185
int colors
Definition server.h:236
signed char movement_count[NETGRAPH_PACKETS]
Definition server.h:213
qbool begun
false = don't send datagrams
Definition server.h:193
char download_name[MAX_QPATH]
Definition server.h:289
prvm_vec_t spawn_parms[NUM_SPAWN_PARMS]
spawn parms are carried from level to level
Definition server.h:232
entityframe_database_t * entitydatabase
Definition server.h:272
unsigned int movesequence
Definition server.h:212
qbool clientconnectcalled
false = don't do ClientDisconnect on drop
Definition server.h:187
int frags
Definition server.h:237
float nametime
prevent animated names
Definition server.h:260
double clmovement_disabletimeout
this is used by sv_clmovement_minping code
Definition server.h:227
int sendsignon
1 = send svc_serverinfo and advance to 2, 2 doesn't send, then advances to 0 (allowing unlimited send...
Definition server.h:195
entityframe5_database_t * entitydatabase5
Definition server.h:274
qbool prespawned
false = don't allow spawn
Definition server.h:189
char name[MAX_SCOREBOARDNAME]
Definition server.h:235
entityframe4_database_t * entitydatabase4
Definition server.h:273
int latestframenum
latest received clc_ackframe (used to detect packet loss)
Definition server.h:263
qfile_t * download_file
Definition server.h:286
netconn_t * netconnection
communications handle
Definition server.h:210
int download_expectedposition
next position the client should ack
Definition server.h:287
qbool spawned
false = don't allow begin
Definition server.h:191
prvm_edict_t * edict
PRVM_EDICT_NUM(clientnum+1)
Definition server.h:221
unsigned int movement_highestsequence_seen
Definition server.h:214
float ping
LadyHavoc: can be used for prediction or whatever...
Definition server.h:224
qbool download_started
Definition server.h:288
usercmd_t cmd
movement
Definition server.h:216
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
Definition cmd.h:127
Definition cvar.h:66
float value
Definition cvar.h:74
int integer
Definition cvar.h:73
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
Definition host.h:46
netgraphitem_t incoming_netgraph[NETGRAPH_PACKETS]
Definition netconn.h:227
sizebuf_t message
writing buffer to send to peer as the next reliable message can be added to at any time,...
Definition netconn.h:161
int unreliablebytes
Definition netconn.h:136
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
struct client_s * clients
client slots
Definition server.h:30
int maxclients
number of svs.clients slots (updated by maxplayers command)
Definition server.h:28
double time
Definition server.h:76
char lightstyles[MAX_LIGHTSTYLES][64]
Definition server.h:122
double frametime
Definition server.h:77
qbool paused
Definition server.h:68
sizebuf_t signon
Definition server.h:133
qbool loadgame
handle connections specially
Definition server.h:71
protocolversion_t protocol
one of the PROTOCOL_ values
Definition server.h:74
unsigned char * data
Definition common.h:52
int cursize
Definition common.h:54
qbool badread
Definition common.h:56
int readcount
Definition common.h:55
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
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
cvar_t sv_rollangle
Definition sv_main.c:176
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
cvar_t sv_gameplayfix_q2airaccelerate
Definition sv_main.c:119
cvar_t sv_rollspeed
Definition sv_main.c:175
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
cvar_t sv_autodemo_perclient
Definition sv_main.c:211
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