summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/sv_main.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2018-02-11 15:34:30 -0500
committerFranklin Wei <git@fwei.tk>2019-07-19 22:37:40 -0400
commit5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4 (patch)
tree84406e21639529a185556a33e5de7f43cffc277b /apps/plugins/sdl/progs/quake/sv_main.c
parentb70fecf21ddc21877ec1ae7888d9c18a979e37ad (diff)
downloadrockbox-5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4.tar.gz
rockbox-5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4.zip
Quake!
This ports id Software's Quake to run on the SDL plugin runtime. The source code originated from id under the GPLv2 license. I used https://github.com/ahefner/sdlquake as the base of my port. Performance is, unsurprisingly, not on par with what you're probably used to on PC. I average about 10FPS on ipod6g, but it's still playable. Sound works well enough, but in-game music is not supported. I've written ARM assembly routines for the inner sound loop. Make sure you turn the "brightness" all the way down, or colors will look funky. To run, extract Quake's data files to /.rockbox/quake. Have fun! Change-Id: I4285036e967d7f0722802d43cf2096c808ca5799
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