summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/sv_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/quake/sv_main.c')
-rw-r--r--apps/plugins/sdl/progs/quake/sv_main.c1209
1 files changed, 1209 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/sv_main.c b/apps/plugins/sdl/progs/quake/sv_main.c
new file mode 100644
index 0000000000..5ea62f1efa
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/sv_main.c
@@ -0,0 +1,1209 @@
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_main.c -- server main program
21
22#include "quakedef.h"
23
24server_t sv;
25server_static_t svs;
26
27char localmodels[MAX_MODELS][5]; // inline model names for precache
28
29//============================================================================
30
31/*
32===============
33SV_Init
34===============
35*/
36void SV_Init (void)
37{
38 int i;
39 extern cvar_t sv_maxvelocity;
40 extern cvar_t sv_gravity;
41 extern cvar_t sv_nostep;
42 extern cvar_t sv_friction;
43 extern cvar_t sv_edgefriction;
44 extern cvar_t sv_stopspeed;
45 extern cvar_t sv_maxspeed;
46 extern cvar_t sv_accelerate;
47 extern cvar_t sv_idealpitchscale;
48 extern cvar_t sv_aim;
49
50 Cvar_RegisterVariable (&sv_maxvelocity);
51 Cvar_RegisterVariable (&sv_gravity);
52 Cvar_RegisterVariable (&sv_friction);
53 Cvar_RegisterVariable (&sv_edgefriction);
54 Cvar_RegisterVariable (&sv_stopspeed);
55 Cvar_RegisterVariable (&sv_maxspeed);
56 Cvar_RegisterVariable (&sv_accelerate);
57 Cvar_RegisterVariable (&sv_idealpitchscale);
58 Cvar_RegisterVariable (&sv_aim);
59 Cvar_RegisterVariable (&sv_nostep);
60
61 for (i=0 ; i<MAX_MODELS ; i++)
62 sprintf (localmodels[i], "*%i", i);
63}
64
65/*
66=============================================================================
67
68EVENT MESSAGES
69
70=============================================================================
71*/
72
73/*
74==================
75SV_StartParticle
76
77Make sure the event gets sent to all clients
78==================
79*/
80void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count)
81{
82 int i, v;
83
84 if (sv.datagram.cursize > MAX_DATAGRAM-16)
85 return;
86 MSG_WriteByte (&sv.datagram, svc_particle);
87 MSG_WriteCoord (&sv.datagram, org[0]);
88 MSG_WriteCoord (&sv.datagram, org[1]);
89 MSG_WriteCoord (&sv.datagram, org[2]);
90 for (i=0 ; i<3 ; i++)
91 {
92 v = dir[i]*16;
93 if (v > 127)
94 v = 127;
95 else if (v < -128)
96 v = -128;
97 MSG_WriteChar (&sv.datagram, v);
98 }
99 MSG_WriteByte (&sv.datagram, count);
100 MSG_WriteByte (&sv.datagram, color);
101}
102
103/*
104==================
105SV_StartSound
106
107Each entity can have eight independant sound sources, like voice,
108weapon, feet, etc.
109
110Channel 0 is an auto-allocate channel, the others override anything
111allready running on that entity/channel pair.
112
113An attenuation of 0 will play full volume everywhere in the level.
114Larger attenuations will drop off. (max 4 attenuation)
115
116==================
117*/
118void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
119 float attenuation)
120{
121 int sound_num;
122 int field_mask;
123 int i;
124 int ent;
125
126 if (volume < 0 || volume > 255)
127 Sys_Error ("SV_StartSound: volume = %i", volume);
128
129 if (attenuation < 0 || attenuation > 4)
130 Sys_Error ("SV_StartSound: attenuation = %f", attenuation);
131
132 if (channel < 0 || channel > 7)
133 Sys_Error ("SV_StartSound: channel = %i", channel);
134
135 if (sv.datagram.cursize > MAX_DATAGRAM-16)
136 return;
137
138// find precache number for sound
139 for (sound_num=1 ; sound_num<MAX_SOUNDS
140 && sv.sound_precache[sound_num] ; sound_num++)
141 if (!strcmp(sample, sv.sound_precache[sound_num]))
142 break;
143
144 if ( sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num] )
145 {
146 Con_Printf ("SV_StartSound: %s not precacheed\n", sample);
147 return;
148 }
149
150 ent = NUM_FOR_EDICT(entity);
151
152 channel = (ent<<3) | channel;
153
154 field_mask = 0;
155 if (volume != DEFAULT_SOUND_PACKET_VOLUME)
156 field_mask |= SND_VOLUME;
157 if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
158 field_mask |= SND_ATTENUATION;
159
160// directed messages go only to the entity the are targeted on
161 MSG_WriteByte (&sv.datagram, svc_sound);
162 MSG_WriteByte (&sv.datagram, field_mask);
163 if (field_mask & SND_VOLUME)
164 MSG_WriteByte (&sv.datagram, volume);
165 if (field_mask & SND_ATTENUATION)
166 MSG_WriteByte (&sv.datagram, attenuation*64);
167 MSG_WriteShort (&sv.datagram, channel);
168 MSG_WriteByte (&sv.datagram, sound_num);
169 for (i=0 ; i<3 ; i++)
170 MSG_WriteCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]));
171}
172
173/*
174==============================================================================
175
176CLIENT SPAWNING
177
178==============================================================================
179*/
180
181/*
182================
183SV_SendServerinfo
184
185Sends the first message from the server to a connected client.
186This will be sent on the initial connection and upon each server load.
187================
188*/
189void SV_SendServerinfo (client_t *client)
190{
191 char **s;
192 char message[2048];
193
194 MSG_WriteByte (&client->message, svc_print);
195 sprintf (message, "%c\nVERSION %4.2f SERVER (%i CRC)", 2, VERSION, pr_crc);
196 MSG_WriteString (&client->message,message);
197
198 MSG_WriteByte (&client->message, svc_serverinfo);
199 MSG_WriteLong (&client->message, PROTOCOL_VERSION);
200 MSG_WriteByte (&client->message, svs.maxclients);
201
202 if (!coop.value && deathmatch.value)
203 MSG_WriteByte (&client->message, GAME_DEATHMATCH);
204 else
205 MSG_WriteByte (&client->message, GAME_COOP);
206
207 sprintf (message, pr_strings+sv.edicts->v.message);
208
209 MSG_WriteString (&client->message,message);
210
211 for (s = sv.model_precache+1 ; *s ; s++)
212 MSG_WriteString (&client->message, *s);
213 MSG_WriteByte (&client->message, 0);
214
215 for (s = sv.sound_precache+1 ; *s ; s++)
216 MSG_WriteString (&client->message, *s);
217 MSG_WriteByte (&client->message, 0);
218
219// send music
220 MSG_WriteByte (&client->message, svc_cdtrack);
221 MSG_WriteByte (&client->message, sv.edicts->v.sounds);
222 MSG_WriteByte (&client->message, sv.edicts->v.sounds);
223
224// set view
225 MSG_WriteByte (&client->message, svc_setview);
226 MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict));
227
228 MSG_WriteByte (&client->message, svc_signonnum);
229 MSG_WriteByte (&client->message, 1);
230
231 client->sendsignon = true;
232 client->spawned = false; // need prespawn, spawn, etc
233}
234
235/*
236================
237SV_ConnectClient
238
239Initializes a client_t for a new net connection. This will only be called
240once for a player each game, not once for each level change.
241================
242*/
243void SV_ConnectClient (int clientnum)
244{
245 edict_t *ent;
246 client_t *client;
247 int edictnum;
248 struct qsocket_s *netconnection;
249 int i;
250 float spawn_parms[NUM_SPAWN_PARMS];
251
252 client = svs.clients + clientnum;
253
254 Con_DPrintf ("Client %s connected\n", client->netconnection->address);
255
256 edictnum = clientnum+1;
257
258 ent = EDICT_NUM(edictnum);
259
260// set up the client_t
261 netconnection = client->netconnection;
262
263 if (sv.loadgame)
264 memcpy (spawn_parms, client->spawn_parms, sizeof(spawn_parms));
265 memset (client, 0, sizeof(*client));
266 client->netconnection = netconnection;
267
268 strcpy (client->name, "unconnected");
269 client->active = true;
270 client->spawned = false;
271 client->edict = ent;
272 client->message.data = client->msgbuf;
273 client->message.maxsize = sizeof(client->msgbuf);
274 client->message.allowoverflow = true; // we can catch it
275
276#ifdef IDGODS
277 client->privileged = IsID(&client->netconnection->addr);
278#else
279 client->privileged = false;
280#endif
281
282 if (sv.loadgame)
283 memcpy (client->spawn_parms, spawn_parms, sizeof(spawn_parms));
284 else
285 {
286 // call the progs to get default spawn parms for the new client
287 PR_ExecuteProgram (pr_global_struct->SetNewParms);
288 for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
289 client->spawn_parms[i] = (&pr_global_struct->parm1)[i];
290 }
291
292 SV_SendServerinfo (client);
293}
294
295
296/*
297===================
298SV_CheckForNewClients
299
300===================
301*/
302void SV_CheckForNewClients (void)
303{
304 struct qsocket_s *ret;
305 int i;
306
307//
308// check for new connections
309//
310 while (1)
311 {
312 ret = NET_CheckNewConnections ();
313 if (!ret)
314 break;
315
316 //
317 // init a new client structure
318 //
319 for (i=0 ; i<svs.maxclients ; i++)
320 if (!svs.clients[i].active)
321 break;
322 if (i == svs.maxclients)
323 Sys_Error ("Host_CheckForNewClients: no free clients");
324
325 svs.clients[i].netconnection = ret;
326 SV_ConnectClient (i);
327
328 net_activeconnections++;
329 }
330}
331
332
333
334/*
335===============================================================================
336
337FRAME UPDATES
338
339===============================================================================
340*/
341
342/*
343==================
344SV_ClearDatagram
345
346==================
347*/
348void SV_ClearDatagram (void)
349{
350 SZ_Clear (&sv.datagram);
351}
352
353/*
354=============================================================================
355
356The PVS must include a small area around the client to allow head bobbing
357or other small motion on the client side. Otherwise, a bob might cause an
358entity that should be visible to not show up, especially when the bob
359crosses a waterline.
360
361=============================================================================
362*/
363
364int fatbytes;
365byte fatpvs[MAX_MAP_LEAFS/8];
366
367void SV_AddToFatPVS (vec3_t org, mnode_t *node)
368{
369 int i;
370 byte *pvs;
371 mplane_t *plane;
372 float d;
373
374 while (1)
375 {
376 // if this is a leaf, accumulate the pvs bits
377 if (node->contents < 0)
378 {
379 if (node->contents != CONTENTS_SOLID)
380 {
381 pvs = Mod_LeafPVS ( (mleaf_t *)node, sv.worldmodel);
382 for (i=0 ; i<fatbytes ; i++)
383 fatpvs[i] |= pvs[i];
384 }
385 return;
386 }
387
388 plane = node->plane;
389 d = DotProduct (org, plane->normal) - plane->dist;
390 if (d > 8)
391 node = node->children[0];
392 else if (d < -8)
393 node = node->children[1];
394 else
395 { // go down both
396 SV_AddToFatPVS (org, node->children[0]);
397 node = node->children[1];
398 }
399 }
400}
401
402/*
403=============
404SV_FatPVS
405
406Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the
407given point.
408=============
409*/
410byte *SV_FatPVS (vec3_t org)
411{
412 fatbytes = (sv.worldmodel->numleafs+31)>>3;
413 Q_memset (fatpvs, 0, fatbytes);
414 SV_AddToFatPVS (org, sv.worldmodel->nodes);
415 return fatpvs;
416}
417
418//=============================================================================
419
420
421/*
422=============
423SV_WriteEntitiesToClient
424
425=============
426*/
427void SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
428{
429 int e, i;
430 int bits;
431 byte *pvs;
432 vec3_t org;
433 float miss;
434 edict_t *ent;
435
436// find the client's PVS
437 VectorAdd (clent->v.origin, clent->v.view_ofs, org);
438 pvs = SV_FatPVS (org);
439
440// send over all entities (excpet the client) that touch the pvs
441 ent = NEXT_EDICT(sv.edicts);
442 for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
443 {
444#ifdef QUAKE2
445 // don't send if flagged for NODRAW and there are no lighting effects
446 if (ent->v.effects == EF_NODRAW)
447 continue;
448#endif
449
450// ignore if not touching a PV leaf
451 if (ent != clent) // clent is ALLWAYS sent
452 {
453// ignore ents without visible models
454 if (!ent->v.modelindex || !pr_strings[ent->v.model])
455 continue;
456
457 for (i=0 ; i < ent->num_leafs ; i++)
458 if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i]&7) ))
459 break;
460
461 if (i == ent->num_leafs)
462 continue; // not visible
463 }
464
465 if (msg->maxsize - msg->cursize < 16)
466 {
467 Con_Printf ("packet overflow\n");
468 return;
469 }
470
471// send an update
472 bits = 0;
473
474 for (i=0 ; i<3 ; i++)
475 {
476 miss = ent->v.origin[i] - ent->baseline.origin[i];
477 if ( miss < -0.1 || miss > 0.1 )
478 bits |= U_ORIGIN1<<i;
479 }
480
481 if ( ent->v.angles[0] != ent->baseline.angles[0] )
482 bits |= U_ANGLE1;
483
484 if ( ent->v.angles[1] != ent->baseline.angles[1] )
485 bits |= U_ANGLE2;
486
487 if ( ent->v.angles[2] != ent->baseline.angles[2] )
488 bits |= U_ANGLE3;
489
490 if (ent->v.movetype == MOVETYPE_STEP)
491 bits |= U_NOLERP; // don't mess up the step animation
492
493 if (ent->baseline.colormap != ent->v.colormap)
494 bits |= U_COLORMAP;
495
496 if (ent->baseline.skin != ent->v.skin)
497 bits |= U_SKIN;
498
499 if (ent->baseline.frame != ent->v.frame)
500 bits |= U_FRAME;
501
502 if (ent->baseline.effects != ent->v.effects)
503 bits |= U_EFFECTS;
504
505 if (ent->baseline.modelindex != ent->v.modelindex)
506 bits |= U_MODEL;
507
508 if (e >= 256)
509 bits |= U_LONGENTITY;
510
511 if (bits >= 256)
512 bits |= U_MOREBITS;
513
514 //
515 // write the message
516 //
517 MSG_WriteByte (msg,bits | U_SIGNAL);
518
519 if (bits & U_MOREBITS)
520 MSG_WriteByte (msg, bits>>8);
521 if (bits & U_LONGENTITY)
522 MSG_WriteShort (msg,e);
523 else
524 MSG_WriteByte (msg,e);
525
526 if (bits & U_MODEL)
527 MSG_WriteByte (msg, ent->v.modelindex);
528 if (bits & U_FRAME)
529 MSG_WriteByte (msg, ent->v.frame);
530 if (bits & U_COLORMAP)
531 MSG_WriteByte (msg, ent->v.colormap);
532 if (bits & U_SKIN)
533 MSG_WriteByte (msg, ent->v.skin);
534 if (bits & U_EFFECTS)
535 MSG_WriteByte (msg, ent->v.effects);
536 if (bits & U_ORIGIN1)
537 MSG_WriteCoord (msg, ent->v.origin[0]);
538 if (bits & U_ANGLE1)
539 MSG_WriteAngle(msg, ent->v.angles[0]);
540 if (bits & U_ORIGIN2)
541 MSG_WriteCoord (msg, ent->v.origin[1]);
542 if (bits & U_ANGLE2)
543 MSG_WriteAngle(msg, ent->v.angles[1]);
544 if (bits & U_ORIGIN3)
545 MSG_WriteCoord (msg, ent->v.origin[2]);
546 if (bits & U_ANGLE3)
547 MSG_WriteAngle(msg, ent->v.angles[2]);
548 }
549}
550
551/*
552=============
553SV_CleanupEnts
554
555=============
556*/
557void SV_CleanupEnts (void)
558{
559 int e;
560 edict_t *ent;
561
562 ent = NEXT_EDICT(sv.edicts);
563 for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
564 {
565 ent->v.effects = (int)ent->v.effects & ~EF_MUZZLEFLASH;
566 }
567
568}
569
570/*
571==================
572SV_WriteClientdataToMessage
573
574==================
575*/
576void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
577{
578 int bits;
579 int i;
580 edict_t *other;
581 int items;
582#ifndef QUAKE2
583 eval_t *val;
584#endif
585
586//
587// send a damage message
588//
589 if (ent->v.dmg_take || ent->v.dmg_save)
590 {
591 other = PROG_TO_EDICT(ent->v.dmg_inflictor);
592 MSG_WriteByte (msg, svc_damage);
593 MSG_WriteByte (msg, ent->v.dmg_save);
594 MSG_WriteByte (msg, ent->v.dmg_take);
595 for (i=0 ; i<3 ; i++)
596 MSG_WriteCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i]));
597
598 ent->v.dmg_take = 0;
599 ent->v.dmg_save = 0;
600 }
601
602//
603// send the current viewpos offset from the view entity
604//
605 SV_SetIdealPitch (); // how much to look up / down ideally
606
607// a fixangle might get lost in a dropped packet. Oh well.
608 if ( ent->v.fixangle )
609 {
610 MSG_WriteByte (msg, svc_setangle);
611 for (i=0 ; i < 3 ; i++)
612 MSG_WriteAngle (msg, ent->v.angles[i] );
613 ent->v.fixangle = 0;
614 }
615
616 bits = 0;
617
618 if (ent->v.view_ofs[2] != DEFAULT_VIEWHEIGHT)
619 bits |= SU_VIEWHEIGHT;
620
621 if (ent->v.idealpitch)
622 bits |= SU_IDEALPITCH;
623
624// stuff the sigil bits into the high bits of items for sbar, or else
625// mix in items2
626#ifdef QUAKE2
627 items = (int)ent->v.items | ((int)ent->v.items2 << 23);
628#else
629 val = GetEdictFieldValue(ent, "items2");
630
631 if (val)
632 items = (int)ent->v.items | ((int)val->_float << 23);
633 else
634 items = (int)ent->v.items | ((int)pr_global_struct->serverflags << 28);
635#endif
636
637 bits |= SU_ITEMS;
638
639 if ( (int)ent->v.flags & FL_ONGROUND)
640 bits |= SU_ONGROUND;
641
642 if ( ent->v.waterlevel >= 2)
643 bits |= SU_INWATER;
644
645 for (i=0 ; i<3 ; i++)
646 {
647 if (ent->v.punchangle[i])
648 bits |= (SU_PUNCH1<<i);
649 if (ent->v.velocity[i])
650 bits |= (SU_VELOCITY1<<i);
651 }
652
653 if (ent->v.weaponframe)
654 bits |= SU_WEAPONFRAME;
655
656 if (ent->v.armorvalue)
657 bits |= SU_ARMOR;
658
659// if (ent->v.weapon)
660 bits |= SU_WEAPON;
661
662// send the data
663
664 MSG_WriteByte (msg, svc_clientdata);
665 MSG_WriteShort (msg, bits);
666
667 if (bits & SU_VIEWHEIGHT)
668 MSG_WriteChar (msg, ent->v.view_ofs[2]);
669
670 if (bits & SU_IDEALPITCH)
671 MSG_WriteChar (msg, ent->v.idealpitch);
672
673 for (i=0 ; i<3 ; i++)
674 {
675 if (bits & (SU_PUNCH1<<i))
676 MSG_WriteChar (msg, ent->v.punchangle[i]);
677 if (bits & (SU_VELOCITY1<<i))
678 MSG_WriteChar (msg, ent->v.velocity[i]/16);
679 }
680
681// [always sent] if (bits & SU_ITEMS)
682 MSG_WriteLong (msg, items);
683
684 if (bits & SU_WEAPONFRAME)
685 MSG_WriteByte (msg, ent->v.weaponframe);
686 if (bits & SU_ARMOR)
687 MSG_WriteByte (msg, ent->v.armorvalue);
688 if (bits & SU_WEAPON)
689 MSG_WriteByte (msg, SV_ModelIndex(pr_strings+ent->v.weaponmodel));
690
691 MSG_WriteShort (msg, ent->v.health);
692 MSG_WriteByte (msg, ent->v.currentammo);
693 MSG_WriteByte (msg, ent->v.ammo_shells);
694 MSG_WriteByte (msg, ent->v.ammo_nails);
695 MSG_WriteByte (msg, ent->v.ammo_rockets);
696 MSG_WriteByte (msg, ent->v.ammo_cells);
697
698 if (standard_quake)
699 {
700 MSG_WriteByte (msg, ent->v.weapon);
701 }
702 else
703 {
704 for(i=0;i<32;i++)
705 {
706 if ( ((int)ent->v.weapon) & (1<<i) )
707 {
708 MSG_WriteByte (msg, i);
709 break;
710 }
711 }
712 }
713}
714
715/*
716=======================
717SV_SendClientDatagram
718=======================
719*/
720qboolean SV_SendClientDatagram (client_t *client)
721{
722 byte buf[MAX_DATAGRAM];
723 sizebuf_t msg;
724
725 msg.data = buf;
726 msg.maxsize = sizeof(buf);
727 msg.cursize = 0;
728
729 MSG_WriteByte (&msg, svc_time);
730 MSG_WriteFloat (&msg, sv.time);
731
732// add the client specific data to the datagram
733 SV_WriteClientdataToMessage (client->edict, &msg);
734
735 SV_WriteEntitiesToClient (client->edict, &msg);
736
737// copy the server datagram if there is space
738 if (msg.cursize + sv.datagram.cursize < msg.maxsize)
739 SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
740
741// send the datagram
742 if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1)
743 {
744 SV_DropClient (true);// if the message couldn't send, kick off
745 return false;
746 }
747
748 return true;
749}
750
751/*
752=======================
753SV_UpdateToReliableMessages
754=======================
755*/
756void SV_UpdateToReliableMessages (void)
757{
758 int i, j;
759 client_t *client;
760
761// check for changes to be sent over the reliable streams
762 for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
763 {
764 if (host_client->old_frags != host_client->edict->v.frags)
765 {
766 for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
767 {
768 if (!client->active)
769 continue;
770 MSG_WriteByte (&client->message, svc_updatefrags);
771 MSG_WriteByte (&client->message, i);
772 MSG_WriteShort (&client->message, host_client->edict->v.frags);
773 }
774
775 host_client->old_frags = host_client->edict->v.frags;
776 }
777 }
778
779 for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
780 {
781 if (!client->active)
782 continue;
783 SZ_Write (&client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
784 }
785
786 SZ_Clear (&sv.reliable_datagram);
787}
788
789
790/*
791=======================
792SV_SendNop
793
794Send a nop message without trashing or sending the accumulated client
795message buffer
796=======================
797*/
798void SV_SendNop (client_t *client)
799{
800 sizebuf_t msg;
801 byte buf[4];
802
803 msg.data = buf;
804 msg.maxsize = sizeof(buf);
805 msg.cursize = 0;
806
807 MSG_WriteChar (&msg, svc_nop);
808
809 if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1)
810 SV_DropClient (true); // if the message couldn't send, kick off
811 client->last_message = realtime;
812}
813
814/*
815=======================
816SV_SendClientMessages
817=======================
818*/
819void SV_SendClientMessages (void)
820{
821 int i;
822
823// update frags, names, etc
824 SV_UpdateToReliableMessages ();
825
826// build individual updates
827 for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
828 {
829 if (!host_client->active)
830 continue;
831
832 if (host_client->spawned)
833 {
834 if (!SV_SendClientDatagram (host_client))
835 continue;
836 }
837 else
838 {
839 // the player isn't totally in the game yet
840 // send small keepalive messages if too much time has passed
841 // send a full message when the next signon stage has been requested
842 // some other message data (name changes, etc) may accumulate
843 // between signon stages
844 if (!host_client->sendsignon)
845 {
846 if (realtime - host_client->last_message > 5)
847 SV_SendNop (host_client);
848 continue; // don't send out non-signon messages
849 }
850 }
851
852 // check for an overflowed message. Should only happen
853 // on a very fucked up connection that backs up a lot, then
854 // changes level
855 if (host_client->message.overflowed)
856 {
857 SV_DropClient (true);
858 host_client->message.overflowed = false;
859 continue;
860 }
861
862 if (host_client->message.cursize || host_client->dropasap)
863 {
864 if (!NET_CanSendMessage (host_client->netconnection))
865 {
866// I_Printf ("can't write\n");
867 continue;
868 }
869
870 if (host_client->dropasap)
871 SV_DropClient (false); // went to another level
872 else
873 {
874 if (NET_SendMessage (host_client->netconnection
875 , &host_client->message) == -1)
876 SV_DropClient (true); // if the message couldn't send, kick off
877 SZ_Clear (&host_client->message);
878 host_client->last_message = realtime;
879 host_client->sendsignon = false;
880 }
881 }
882 }
883
884
885// clear muzzle flashes
886 SV_CleanupEnts ();
887}
888
889
890/*
891==============================================================================
892
893SERVER SPAWNING
894
895==============================================================================
896*/
897
898/*
899================
900SV_ModelIndex
901
902================
903*/
904int SV_ModelIndex (char *name)
905{
906 int i;
907
908 if (!name || !name[0])
909 return 0;
910
911 for (i=0 ; i<MAX_MODELS && sv.model_precache[i] ; i++)
912 if (!strcmp(sv.model_precache[i], name))
913 return i;
914 if (i==MAX_MODELS || !sv.model_precache[i])
915 Sys_Error ("SV_ModelIndex: model %s not precached", name);
916 return i;
917}
918
919/*
920================
921SV_CreateBaseline
922
923================
924*/
925void SV_CreateBaseline (void)
926{
927 int i;
928 edict_t *svent;
929 int entnum;
930
931 for (entnum = 0; entnum < sv.num_edicts ; entnum++)
932 {
933 // get the current server version
934 svent = EDICT_NUM(entnum);
935 if (svent->free)
936 continue;
937 if (entnum > svs.maxclients && !svent->v.modelindex)
938 continue;
939
940 //
941 // create entity baseline
942 //
943 VectorCopy (svent->v.origin, svent->baseline.origin);
944 VectorCopy (svent->v.angles, svent->baseline.angles);
945 svent->baseline.frame = svent->v.frame;
946 svent->baseline.skin = svent->v.skin;
947 if (entnum > 0 && entnum <= svs.maxclients)
948 {
949 svent->baseline.colormap = entnum;
950 svent->baseline.modelindex = SV_ModelIndex("progs/player.mdl");
951 }
952 else
953 {
954 svent->baseline.colormap = 0;
955 svent->baseline.modelindex =
956 SV_ModelIndex(pr_strings + svent->v.model);
957 }
958
959 //
960 // add to the message
961 //
962 MSG_WriteByte (&sv.signon,svc_spawnbaseline);
963 MSG_WriteShort (&sv.signon,entnum);
964
965 MSG_WriteByte (&sv.signon, svent->baseline.modelindex);
966 MSG_WriteByte (&sv.signon, svent->baseline.frame);
967 MSG_WriteByte (&sv.signon, svent->baseline.colormap);
968 MSG_WriteByte (&sv.signon, svent->baseline.skin);
969 for (i=0 ; i<3 ; i++)
970 {
971 MSG_WriteCoord(&sv.signon, svent->baseline.origin[i]);
972 MSG_WriteAngle(&sv.signon, svent->baseline.angles[i]);
973 }
974 }
975}
976
977
978/*
979================
980SV_SendReconnect
981
982Tell all the clients that the server is changing levels
983================
984*/
985void SV_SendReconnect (void)
986{
987 char data[128];
988 sizebuf_t msg;
989
990 msg.data = data;
991 msg.cursize = 0;
992 msg.maxsize = sizeof(data);
993
994 MSG_WriteChar (&msg, svc_stufftext);
995 MSG_WriteString (&msg, "reconnect\n");
996 NET_SendToAll (&msg, 5);
997
998 if (cls.state != ca_dedicated)
999#ifdef QUAKE2
1000 Cbuf_InsertText ("reconnect\n");
1001#else
1002 Cmd_ExecuteString ("reconnect\n", src_command);
1003#endif
1004}
1005
1006
1007/*
1008================
1009SV_SaveSpawnparms
1010
1011Grabs the current state of each client for saving across the
1012transition to another level
1013================
1014*/
1015void SV_SaveSpawnparms (void)
1016{
1017 int i, j;
1018
1019 svs.serverflags = pr_global_struct->serverflags;
1020
1021 for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
1022 {
1023 if (!host_client->active)
1024 continue;
1025
1026 // call the progs to get default spawn parms for the new client
1027 pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
1028 PR_ExecuteProgram (pr_global_struct->SetChangeParms);
1029 for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
1030 host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j];
1031 }
1032}
1033
1034
1035/*
1036================
1037SV_SpawnServer
1038
1039This is called at the start of each level
1040================
1041*/
1042extern float scr_centertime_off;
1043
1044#ifdef QUAKE2
1045void SV_SpawnServer (char *server, char *startspot)
1046#else
1047void SV_SpawnServer (char *server)
1048#endif
1049{
1050 edict_t *ent;
1051 int i;
1052
1053 // let's not have any servers with no name
1054 if (hostname.string[0] == 0)
1055 Cvar_Set ("hostname", "UNNAMED");
1056 scr_centertime_off = 0;
1057
1058 Con_DPrintf ("SpawnServer: %s\n",server);
1059 svs.changelevel_issued = false; // now safe to issue another
1060
1061//
1062// tell all connected clients that we are going to a new level
1063//
1064 if (sv.active)
1065 {
1066 SV_SendReconnect ();
1067 }
1068
1069//
1070// make cvars consistant
1071//
1072 if (coop.value)
1073 Cvar_SetValue ("deathmatch", 0);
1074 current_skill = (int)(skill.value + 0.5);
1075 if (current_skill < 0)
1076 current_skill = 0;
1077 if (current_skill > 3)
1078 current_skill = 3;
1079
1080 Cvar_SetValue ("skill", (float)current_skill);
1081
1082//
1083// set up the new server
1084//
1085 Host_ClearMemory ();
1086
1087 memset (&sv, 0, sizeof(sv));
1088
1089 strcpy (sv.name, server);
1090#ifdef QUAKE2
1091 if (startspot)
1092 strcpy(sv.startspot, startspot);
1093#endif
1094
1095// load progs to get entity field count
1096 //printf("progs 1");
1097 PR_LoadProgs ();
1098 //printf("progs 2");
1099
1100// allocate server memory
1101 sv.max_edicts = MAX_EDICTS;
1102
1103 sv.edicts = Hunk_AllocName (sv.max_edicts*pr_edict_size, "edicts");
1104
1105 sv.datagram.maxsize = sizeof(sv.datagram_buf);
1106 sv.datagram.cursize = 0;
1107 sv.datagram.data = sv.datagram_buf;
1108
1109 sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf);
1110 sv.reliable_datagram.cursize = 0;
1111 sv.reliable_datagram.data = sv.reliable_datagram_buf;
1112
1113 sv.signon.maxsize = sizeof(sv.signon_buf);
1114 sv.signon.cursize = 0;
1115 sv.signon.data = sv.signon_buf;
1116
1117 //printf("progs 3");
1118// leave slots at start for clients only
1119 sv.num_edicts = svs.maxclients+1;
1120 for (i=0 ; i<svs.maxclients ; i++)
1121 {
1122 ent = EDICT_NUM(i+1);
1123 svs.clients[i].edict = ent;
1124 }
1125
1126 sv.state = ss_loading;
1127 sv.paused = false;
1128
1129 sv.time = 1.0;
1130
1131 strcpy (sv.name, server);
1132 sprintf (sv.modelname,"maps/%s.bsp", server);
1133 sv.worldmodel = Mod_ForName (sv.modelname, false);
1134 if (!sv.worldmodel)
1135 {
1136 Con_Printf ("Couldn't spawn server %s\n", sv.modelname);
1137 sv.active = false;
1138 return;
1139 }
1140 sv.models[1] = sv.worldmodel;
1141
1142//
1143// clear world interaction links
1144//
1145 //printf("progs 4");
1146 SV_ClearWorld ();
1147 //printf("progs 5");
1148
1149 sv.sound_precache[0] = pr_strings;
1150
1151 sv.model_precache[0] = pr_strings;
1152 sv.model_precache[1] = sv.modelname;
1153 for (i=1 ; i<sv.worldmodel->numsubmodels ; i++)
1154 {
1155 sv.model_precache[1+i] = localmodels[i];
1156 sv.models[i+1] = Mod_ForName (localmodels[i], false);
1157 }
1158
1159//
1160// load the rest of the entities
1161//
1162 //printf("progs 6");
1163 ent = EDICT_NUM(0);
1164 memset (&ent->v, 0, progs->entityfields * 4);
1165 //printf("progs 7");
1166 ent->free = false;
1167 ent->v.model = sv.worldmodel->name - pr_strings;
1168 ent->v.modelindex = 1; // world model
1169 ent->v.solid = SOLID_BSP;
1170 ent->v.movetype = MOVETYPE_PUSH;
1171
1172 if (coop.value)
1173 pr_global_struct->coop = coop.value;
1174 else
1175 pr_global_struct->deathmatch = deathmatch.value;
1176
1177 pr_global_struct->mapname = sv.name - pr_strings;
1178#ifdef QUAKE2
1179 pr_global_struct->startspot = sv.startspot - pr_strings;
1180#endif
1181
1182// serverflags are for cross level information (sigils)
1183 pr_global_struct->serverflags = svs.serverflags;
1184
1185 //printf("progs 8");
1186 ED_LoadFromFile (sv.worldmodel->entities);
1187
1188 //printf("progs 9");
1189 sv.active = true;
1190
1191// all setup is completed, any further precache statements are errors
1192 sv.state = ss_active;
1193
1194// run two frames to allow everything to settle
1195 host_frametime = 0.1;
1196 SV_Physics ();
1197 SV_Physics ();
1198
1199// create a baseline for more efficient communications
1200 SV_CreateBaseline ();
1201
1202// send serverinfo to all connected clients
1203 for (i=0,host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
1204 if (host_client->active)
1205 SV_SendServerinfo (host_client);
1206
1207 Con_DPrintf ("Server spawned.\n");
1208}
1209