Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5131 | clevermous | 1 | /* |
2 | Copyright (C) 1996-1997 Id Software, Inc. |
||
3 | |||
4 | This program is free software; you can redistribute it and/or |
||
5 | modify it under the terms of the GNU General Public License |
||
6 | as published by the Free Software Foundation; either version 2 |
||
7 | of the License, or (at your option) any later version. |
||
8 | |||
9 | This program is distributed in the hope that it will be useful, |
||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
12 | |||
13 | See the GNU General Public License for more details. |
||
14 | |||
15 | You should have received a copy of the GNU General Public License |
||
16 | along with this program; if not, write to the Free Software |
||
17 | Foundation, 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 | |||
24 | server_t sv; |
||
25 | server_static_t svs; |
||
26 | |||
27 | char localmodels[MAX_MODELS][5]; // inline model names for precache |
||
28 | |||
29 | //============================================================================ |
||
30 | |||
31 | /* |
||
32 | =============== |
||
33 | SV_Init |
||
34 | =============== |
||
35 | */ |
||
36 | void 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 |
||
62 | sprintf (localmodels[i], "*%i", i); |
||
63 | } |
||
64 | |||
65 | /* |
||
66 | ============================================================================= |
||
67 | |||
68 | EVENT MESSAGES |
||
69 | |||
70 | ============================================================================= |
||
71 | */ |
||
72 | |||
73 | /* |
||
74 | ================== |
||
75 | SV_StartParticle |
||
76 | |||
77 | Make sure the event gets sent to all clients |
||
78 | ================== |
||
79 | */ |
||
80 | void 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 | ================== |
||
105 | SV_StartSound |
||
106 | |||
107 | Each entity can have eight independant sound sources, like voice, |
||
108 | weapon, feet, etc. |
||
109 | |||
110 | Channel 0 is an auto-allocate channel, the others override anything |
||
111 | allready running on that entity/channel pair. |
||
112 | |||
113 | An attenuation of 0 will play full volume everywhere in the level. |
||
114 | Larger attenuations will drop off. (max 4 attenuation) |
||
115 | |||
116 | ================== |
||
117 | */ |
||
118 | void 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 |
||
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 | |||
176 | CLIENT SPAWNING |
||
177 | |||
178 | ============================================================================== |
||
179 | */ |
||
180 | |||
181 | /* |
||
182 | ================ |
||
183 | SV_SendServerinfo |
||
184 | |||
185 | Sends the first message from the server to a connected client. |
||
186 | This will be sent on the initial connection and upon each server load. |
||
187 | ================ |
||
188 | */ |
||
189 | void 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 | ================ |
||
237 | SV_ConnectClient |
||
238 | |||
239 | Initializes a client_t for a new net connection. This will only be called |
||
240 | once for a player each game, not once for each level change. |
||
241 | ================ |
||
242 | */ |
||
243 | void 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 |
||
289 | client->spawn_parms[i] = (&pr_global_struct->parm1)[i]; |
||
290 | } |
||
291 | |||
292 | SV_SendServerinfo (client); |
||
293 | } |
||
294 | |||
295 | |||
296 | /* |
||
297 | =================== |
||
298 | SV_CheckForNewClients |
||
299 | |||
300 | =================== |
||
301 | */ |
||
302 | void 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 |
||
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 | |||
337 | FRAME UPDATES |
||
338 | |||
339 | =============================================================================== |
||
340 | */ |
||
341 | |||
342 | /* |
||
343 | ================== |
||
344 | SV_ClearDatagram |
||
345 | |||
346 | ================== |
||
347 | */ |
||
348 | void SV_ClearDatagram (void) |
||
349 | { |
||
350 | SZ_Clear (&sv.datagram); |
||
351 | } |
||
352 | |||
353 | /* |
||
354 | ============================================================================= |
||
355 | |||
356 | The PVS must include a small area around the client to allow head bobbing |
||
357 | or other small motion on the client side. Otherwise, a bob might cause an |
||
358 | entity that should be visible to not show up, especially when the bob |
||
359 | crosses a waterline. |
||
360 | |||
361 | ============================================================================= |
||
362 | */ |
||
363 | |||
364 | int fatbytes; |
||
365 | byte fatpvs[MAX_MAP_LEAFS/8]; |
||
366 | |||
367 | void 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 |
||
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 | ============= |
||
404 | SV_FatPVS |
||
405 | |||
406 | Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the |
||
407 | given point. |
||
408 | ============= |
||
409 | */ |
||
410 | byte *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 | ============= |
||
423 | SV_WriteEntitiesToClient |
||
424 | |||
425 | ============= |
||
426 | */ |
||
427 | void 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 |
||
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< |
||
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 | ============= |
||
553 | SV_CleanupEnts |
||
554 | |||
555 | ============= |
||
556 | */ |
||
557 | void SV_CleanupEnts (void) |
||
558 | { |
||
559 | int e; |
||
560 | edict_t *ent; |
||
561 | |||
562 | ent = NEXT_EDICT(sv.edicts); |
||
563 | for (e=1 ; e |
||
564 | { |
||
565 | ent->v.effects = (int)ent->v.effects & ~EF_MUZZLEFLASH; |
||
566 | } |
||
567 | |||
568 | } |
||
569 | |||
570 | /* |
||
571 | ================== |
||
572 | SV_WriteClientdataToMessage |
||
573 | |||
574 | ================== |
||
575 | */ |
||
576 | void 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< |
||
649 | if (ent->v.velocity[i]) |
||
650 | bits |= (SU_VELOCITY1< |
||
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< |
||
676 | MSG_WriteChar (msg, ent->v.punchangle[i]); |
||
677 | if (bits & (SU_VELOCITY1< |
||
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< |
||
707 | { |
||
708 | MSG_WriteByte (msg, i); |
||
709 | break; |
||
710 | } |
||
711 | } |
||
712 | } |
||
713 | } |
||
714 | |||
715 | /* |
||
716 | ======================= |
||
717 | SV_SendClientDatagram |
||
718 | ======================= |
||
719 | */ |
||
720 | qboolean 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 | ======================= |
||
753 | SV_UpdateToReliableMessages |
||
754 | ======================= |
||
755 | */ |
||
756 | void 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 |
||
763 | { |
||
764 | if (host_client->old_frags != host_client->edict->v.frags) |
||
765 | { |
||
766 | for (j=0, client = svs.clients ; j |
||
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 |
||
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 | ======================= |
||
792 | SV_SendNop |
||
793 | |||
794 | Send a nop message without trashing or sending the accumulated client |
||
795 | message buffer |
||
796 | ======================= |
||
797 | */ |
||
798 | void 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 | ======================= |
||
816 | SV_SendClientMessages |
||
817 | ======================= |
||
818 | */ |
||
819 | void 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 |
||
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 | |||
893 | SERVER SPAWNING |
||
894 | |||
895 | ============================================================================== |
||
896 | */ |
||
897 | |||
898 | /* |
||
899 | ================ |
||
900 | SV_ModelIndex |
||
901 | |||
902 | ================ |
||
903 | */ |
||
904 | int SV_ModelIndex (char *name) |
||
905 | { |
||
906 | int i; |
||
907 | |||
908 | if (!name || !name[0]) |
||
909 | return 0; |
||
910 | |||
911 | for (i=0 ; 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 | ================ |
||
921 | SV_CreateBaseline |
||
922 | |||
923 | ================ |
||
924 | */ |
||
925 | void 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 | ================ |
||
980 | SV_SendReconnect |
||
981 | |||
982 | Tell all the clients that the server is changing levels |
||
983 | ================ |
||
984 | */ |
||
985 | void 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 | ================ |
||
1009 | SV_SaveSpawnparms |
||
1010 | |||
1011 | Grabs the current state of each client for saving across the |
||
1012 | transition to another level |
||
1013 | ================ |
||
1014 | */ |
||
1015 | void 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 |
||
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 |
||
1030 | host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j]; |
||
1031 | } |
||
1032 | } |
||
1033 | |||
1034 | |||
1035 | /* |
||
1036 | ================ |
||
1037 | SV_SpawnServer |
||
1038 | |||
1039 | This is called at the start of each level |
||
1040 | ================ |
||
1041 | */ |
||
1042 | extern float scr_centertime_off; |
||
1043 | |||
1044 | #ifdef QUAKE2 |
||
1045 | void SV_SpawnServer (char *server, char *startspot) |
||
1046 | #else |
||
1047 | void 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 | PR_LoadProgs (); |
||
1097 | |||
1098 | // allocate server memory |
||
1099 | sv.max_edicts = MAX_EDICTS; |
||
1100 | |||
1101 | sv.edicts = Hunk_AllocName (sv.max_edicts*pr_edict_size, "edicts"); |
||
1102 | |||
1103 | sv.datagram.maxsize = sizeof(sv.datagram_buf); |
||
1104 | sv.datagram.cursize = 0; |
||
1105 | sv.datagram.data = sv.datagram_buf; |
||
1106 | |||
1107 | sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf); |
||
1108 | sv.reliable_datagram.cursize = 0; |
||
1109 | sv.reliable_datagram.data = sv.reliable_datagram_buf; |
||
1110 | |||
1111 | sv.signon.maxsize = sizeof(sv.signon_buf); |
||
1112 | sv.signon.cursize = 0; |
||
1113 | sv.signon.data = sv.signon_buf; |
||
1114 | |||
1115 | // leave slots at start for clients only |
||
1116 | sv.num_edicts = svs.maxclients+1; |
||
1117 | for (i=0 ; i |
||
1118 | { |
||
1119 | ent = EDICT_NUM(i+1); |
||
1120 | svs.clients[i].edict = ent; |
||
1121 | } |
||
1122 | |||
1123 | sv.state = ss_loading; |
||
1124 | sv.paused = false; |
||
1125 | |||
1126 | sv.time = 1.0; |
||
1127 | |||
1128 | strcpy (sv.name, server); |
||
1129 | sprintf (sv.modelname,"maps/%s.bsp", server); |
||
1130 | sv.worldmodel = Mod_ForName (sv.modelname, false); |
||
1131 | if (!sv.worldmodel) |
||
1132 | { |
||
1133 | Con_Printf ("Couldn't spawn server %s\n", sv.modelname); |
||
1134 | sv.active = false; |
||
1135 | return; |
||
1136 | } |
||
1137 | sv.models[1] = sv.worldmodel; |
||
1138 | |||
1139 | // |
||
1140 | // clear world interaction links |
||
1141 | // |
||
1142 | SV_ClearWorld (); |
||
1143 | |||
1144 | sv.sound_precache[0] = pr_strings; |
||
1145 | |||
1146 | sv.model_precache[0] = pr_strings; |
||
1147 | sv.model_precache[1] = sv.modelname; |
||
1148 | for (i=1 ; i |
||
1149 | { |
||
1150 | sv.model_precache[1+i] = localmodels[i]; |
||
1151 | sv.models[i+1] = Mod_ForName (localmodels[i], false); |
||
1152 | } |
||
1153 | |||
1154 | // |
||
1155 | // load the rest of the entities |
||
1156 | // |
||
1157 | ent = EDICT_NUM(0); |
||
1158 | memset (&ent->v, 0, progs->entityfields * 4); |
||
1159 | ent->free = false; |
||
1160 | ent->v.model = sv.worldmodel->name - pr_strings; |
||
1161 | ent->v.modelindex = 1; // world model |
||
1162 | ent->v.solid = SOLID_BSP; |
||
1163 | ent->v.movetype = MOVETYPE_PUSH; |
||
1164 | |||
1165 | if (coop.value) |
||
1166 | pr_global_struct->coop = coop.value; |
||
1167 | else |
||
1168 | pr_global_struct->deathmatch = deathmatch.value; |
||
1169 | |||
1170 | pr_global_struct->mapname = sv.name - pr_strings; |
||
1171 | #ifdef QUAKE2 |
||
1172 | pr_global_struct->startspot = sv.startspot - pr_strings; |
||
1173 | #endif |
||
1174 | |||
1175 | // serverflags are for cross level information (sigils) |
||
1176 | pr_global_struct->serverflags = svs.serverflags; |
||
1177 | |||
1178 | ED_LoadFromFile (sv.worldmodel->entities); |
||
1179 | |||
1180 | sv.active = true; |
||
1181 | |||
1182 | // all setup is completed, any further precache statements are errors |
||
1183 | sv.state = ss_active; |
||
1184 | |||
1185 | // run two frames to allow everything to settle |
||
1186 | host_frametime = 0.1; |
||
1187 | SV_Physics (); |
||
1188 | SV_Physics (); |
||
1189 | |||
1190 | // create a baseline for more efficient communications |
||
1191 | SV_CreateBaseline (); |
||
1192 | |||
1193 | // send serverinfo to all connected clients |
||
1194 | for (i=0,host_client = svs.clients ; i |
||
1195 | if (host_client->active) |
||
1196 | SV_SendServerinfo (host_client); |
||
1197 | |||
1198 | Con_DPrintf ("Server spawned.\n"); |
||
1199 | }>3>=>>>32;i++) |
||
1200 |