comparison src/socket.c @ 6:8c6d5731234d

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:04 +0000
parents
children
comparison
equal deleted inserted replaced
5:054275999194 6:8c6d5731234d
1 /*--------------------------------------------------------------------------
2 NETREK II -- Paradise
3
4 Permission to use, copy, modify, and distribute this software and its
5 documentation, or any derivative works thereof, for any NON-COMMERCIAL
6 purpose and without fee is hereby granted, provided that this copyright
7 notice appear in all copies. No representations are made about the
8 suitability of this software for any purpose. This software is provided
9 "as is" without express or implied warranty.
10
11 Xtrek Copyright 1986 Chris Guthrie
12 Netrek (Xtrek II) Copyright 1989 Kevin P. Smith
13 Scott Silvey
14 Paradise II (Netrek II) Copyright 1993 Larry Denys
15 Kurt Olsen
16 Brandon Gillespie
17 --------------------------------------------------------------------------*/
18
19
20 #include "config.h"
21
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/time.h>
26 #include <sys/stat.h>
27 #include <netinet/in.h>
28 #include <netdb.h>
29 #include <math.h>
30 #include <signal.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <zlib.h>
34 #include "defs.h"
35 #include "struct.h"
36 #include "data.h"
37 #include "packets.h"
38 #include "shmem.h"
39 #include "path.h"
40 #include "gppackets.h"
41
42 #ifdef OOPS
43 #ifdef MIPSEL
44 #ifndef htonl
45
46 #define htonl(x) ((u_long) (((u_long) x << 24) | (((u_long) x & 0xff00) << 8) | \
47 (((u_long) x & 0xff0000) >> 8) | ((u_long) x >> 24)))
48 #define ntohl(x) htonl(x)
49 #define htons(x) ((u_short) (((u_short) x << 8) | ((u_short) x >> 8)))
50 #define ntohs(x) htons(x)
51
52 #endif /* htonl */
53 #endif /* MIPSEL */
54 #endif /* OOPS */
55
56 extern void (*r_signal()) ();
57
58 /* #define DOUBLE_UDP /* comment this out to disable it */
59
60 /* #define BROKEN /* for local stress testing; drops 20% of packets */
61 /* #define HOSED /* combine with BROKEN; drops 90% of packets */
62
63 void handleTorpReq(), handlePhasReq(), handleSpeedReq();
64 void handleDirReq(), handleShieldReq(), handleRepairReq(), handleOrbitReq();
65 void handlePractrReq(), handleBombReq(), handleBeamReq(), handleCloakReq();
66 void handleDetTReq(), handleCopilotReq();
67 void handleOutfit(), handleLoginReq();
68 void handlePlasmaReq(), handleWarReq(), handlePlanlockReq();
69 void handlePlaylockReq(), handleDetMReq();
70 void handleTractorReq(), handleRepressReq();
71 void handleCoupReq(), handleRefitReq(), handleMessageReq();
72 void handleQuitReq(), handleOptionsPacket();
73 void handleSocketReq(), handleByeReq();
74 void handleDockingReq(), handleReset();
75 void handleUpdatesReq(), handleReserved();
76 void handleScan();
77 void handleUdpReq(), handleSequence();
78 void handleAskMOTD();
79 void handleRSAKey();
80 void handlePingResponse();
81 #ifdef SHORT_PACKETS
82 void handleShortReq(), handleThresh(), handleSMessageReq();
83 #endif
84 #ifdef FEATURE
85 void handleFeature(), sendFeature(); /* in feature.c */
86 #endif
87
88 static int remoteaddr = -1; /* inet address in net format */
89 extern int errno;
90
91 struct packet_handler handlers[] = {
92 {0}, /* record 0 */
93 {handleMessageReq}, /* CP_MESSAGE */
94 {handleSpeedReq}, /* CP_SPEED */
95 {handleDirReq}, /* CP_DIRECTION */
96 {handlePhasReq}, /* CP_PHASER */
97 {handlePlasmaReq}, /* CP_PLASMA */
98 {handleTorpReq}, /* CP_TORP */
99 {handleQuitReq}, /* CP_QUIT */
100 {handleLoginReq}, /* CP_LOGIN */
101 {handleOutfit}, /* CP_OUTFIT */
102 {handleWarReq}, /* CP_WAR */
103 {handlePractrReq}, /* CP_PRACTR */
104 {handleShieldReq}, /* CP_SHIELD */
105 {handleRepairReq}, /* CP_REPAIR */
106 {handleOrbitReq}, /* CP_ORBIT */
107 {handlePlanlockReq}, /* CP_PLANLOCK */
108 {handlePlaylockReq}, /* CP_PLAYLOCK */
109 {handleBombReq}, /* CP_BOMB */
110 {handleBeamReq}, /* CP_BEAM */
111 {handleCloakReq}, /* CP_CLOAK */
112 {handleDetTReq}, /* CP_DET_TORPS */
113 {handleDetMReq}, /* CP_DET_MYTORP */
114 {handleCopilotReq}, /* CP_COPLIOT */
115 {handleRefitReq}, /* CP_REFIT */
116 {handleTractorReq}, /* CP_TRACTOR */
117 {handleRepressReq}, /* CP_REPRESS */
118 {handleCoupReq}, /* CP_COUP */
119 {handleSocketReq}, /* CP_SOCKET */
120 {handleOptionsPacket}, /* CP_OPTIONS */
121 {handleByeReq}, /* CP_BYE */
122 {handleDockingReq}, /* CP_DOCKPERM */
123 {handleUpdatesReq}, /* CP_UPDATES */
124 {handleReset}, /* CP_RESETSTATS */
125 {handleReserved}, /* CP_RESERVED */
126 {handleScan}, /* CP_SCAN (ATM) */
127 {handleUdpReq}, /* CP_UDP_REQ */
128 {handleSequence}, /* CP_SEQUENCE */
129 {handleRSAKey}, /* CP_RSA_KEY */
130 {handleAskMOTD}, /* CP_ASK_MOTD */
131 {0},
132 {0},
133 {0},
134 {handlePingResponse}, /* CP_PING_RESPONSE */
135 #ifdef SHORT_PACKETS
136 {handleShortReq}, /* CP_S_REQ */
137 {handleThresh}, /* CP_S_THRS */
138 {handleSMessageReq}, /* CP_S_MESSAGE */
139 {0}, /* CP_S_RESERVED */
140 {0}, /* CP_S_DUMMY */
141 #else
142 {0},
143 {0},
144 {0},
145 {0},
146 {0},
147 #endif
148 {0}, /* 48 */
149 {0}, /* 49 */
150 {0}, /* 50 */
151 {0}, /* 51 */
152 {0}, /* 52 */
153 {0}, /* 53 */
154 {0}, /* 54 */
155 {0}, /* 55 */
156 {0}, /* 56 */
157 {0}, /* 57 */
158 {0}, /* 58 */
159 {0}, /* 59 */
160 {handleFeature}, /* CP_FEATURE */
161 {0}
162 };
163 #define NUM_PACKETS (sizeof(handlers) / sizeof(*handlers) - 1)
164
165 int size_of_spacket();
166 int size_of_cpacket();
167
168 int packetsReceived[256] = {0};
169 int packetsSent[256] = {0};
170
171 int clientDead = 0;
172
173 static int udpLocalPort = 0;
174 static int udpClientPort = 0;
175 int udpMode = MODE_SIMPLE; /* what kind of UDP trans we want */
176
177 /* this stuff is used for Fat UDP */
178 typedef void *PTR; /* adjust this if you lack (void *) */
179 typedef struct fat_node_t
180 {
181 PTR packet;
182 int pkt_size;
183 struct fat_node_t *prev;
184 struct fat_node_t *next;
185 } FAT_NODE;
186
187 /* needed for fast lookup of semi-critical fat nodes */
188 extern FAT_NODE fat_kills[MAXPLAYER];
189 extern FAT_NODE fat_torp_info[MAXPLAYER * MAXTORP];
190 extern FAT_NODE fat_thingy_info[TOTALTHINGIES];
191 extern FAT_NODE fat_phaser[MAXPLAYER];
192 extern FAT_NODE fat_plasma_info[MAXPLAYER * MAXPLASMA];
193 extern FAT_NODE fat_you;
194 #if 0
195 extern FAT_NODE fat_status;
196 extern FAT_NODE fat_planet[MAXPLANETS];
197 #else
198 extern FAT_NODE fat_status2;
199 extern FAT_NODE fat_planet2[MAXPLANETS];
200 #endif
201 extern FAT_NODE fat_flags[MAXPLAYER];
202 extern FAT_NODE fat_hostile[MAXPLAYER];
203
204 struct plyr_info_spacket clientPlayersInfo[MAXPLAYER];
205 struct plyr_login_spacket clientLogin[MAXPLAYER];
206 struct hostile_spacket clientHostile[MAXPLAYER];
207 struct stats_spacket clientStats[MAXPLAYER];
208 struct player_spacket clientPlayers[MAXPLAYER];
209 struct kills_spacket clientKills[MAXPLAYER];
210 struct flags_spacket clientFlags[MAXPLAYER];
211 struct pstatus_spacket clientPStatus[MAXPLAYER];
212 int msgCurrent;
213 struct torp_info_spacket clientTorpsInfo[MAXPLAYER * MAXTORP];
214 struct torp_spacket clientTorps[MAXPLAYER * MAXTORP];
215 struct thingy_info_spacket clientThingysInfo[TOTALTHINGIES];
216 struct thingy_spacket clientThingys[TOTALTHINGIES];
217 int clientThingyStatus[TOTALTHINGIES];
218 struct phaser_spacket clientPhasers[MAXPLAYER];
219 struct you_spacket clientSelf;
220 struct pe1_num_missiles_spacket clientMissiles;
221 #if 0
222 struct status_spacket clientStatus;
223 struct planet_spacket clientPlanets[MAXPLANETS];
224 #endif
225 struct planet_loc_spacket clientPlanetLocs[MAXPLANETS];
226 struct plasma_info_spacket clientPlasmasInfo[MAXPLAYER * MAXPLASMA];
227 struct plasma_spacket clientPlasmas[MAXPLAYER * MAXPLASMA];
228 int mustUpdate[MAXPLAYER];
229 struct status_spacket2 clientStatus2; /* new stats packets */
230 struct stats_spacket2 clientStats2[MAXPLAYER];
231 struct planet_spacket2 clientPlanets2[MAXPLANETS];
232
233 #ifdef SHORT_PACKETS
234
235 struct youss_spacket clientSelfShip;
236 struct youshort_spacket clientSelfShort;
237
238 /* HW */
239 static unsigned char clientVPlanets[MAXPLANETS * sizeof(struct planet_s_spacket) + 2 + 6];
240 static int clientVPlanetCount;
241 static int vtsize[9] = {4, 8, 8, 12, 12, 16, 20, 20, 24}; /* How big is the
242 * SP_S_TORP packet */
243 static int vtdata[9] = {0, 3, 5, 7, 9, 12, 14, 16, 18}; /* How big is Torpdata */
244 static int mustsend; /* Flag to remind me that i must send
245 * SP_S_TORP */
246
247 static unsigned char clientVTorps[40];
248
249 static unsigned char clientVTorpsInfo[16];
250
251 static unsigned char clientVPlayers[MAXPLAYER * VPLAYER_SIZE + 16];
252 #if MAXPLAYER > 32
253 static unsigned char clientVXPlayers[33 * 4];
254 #endif
255 static int clientVPlayerCount;
256 static int clientVXPlayerCount;
257 static int big, small;
258
259 static int send_threshold = 0; /* infinity */
260 static int send_short = 0;
261 static int send_mesg = 1;
262 static int send_kmesg = 1;
263 static int send_warn = 1;
264 static int numupdates = 5; /* For threshold */
265 static int actual_threshold = 0;/* == send_threshold / numupdates */
266 static int spk_update_sall = 0; /* Small Update: Only weapons, Kills and
267 * Planets */
268 static int spk_update_all = 0; /* Full Update minus SP_STATS */
269
270 #define SPK_VOFF 0 /* variable packets off */
271 #define SPK_VON 1 /* variable packets on */
272 #define SPK_MOFF 2 /* message packets off */
273 #define SPK_MON 3 /* message packets on */
274 #define SPK_M_KILLS 4
275 #define SPK_M_NOKILLS 5
276 #define SPK_THRESHOLD 6
277 #define SPK_M_WARN 7
278 #define SPK_M_NOWARN 8
279 #define SPK_SALL 9 /* only planets,kills and weapons */
280 #define SPK_ALL 10 /* Full Update - SP_STATS */
281
282 #endif
283
284
285 extern long unsigned int inet_addr( /* ??? */ );
286 void initClientData();
287 void updateTorpInfos();
288 void short_updateTorps(), updateTorps();
289 void updateMissiles();
290 void updateThingies();
291 void updatePlasmas();
292 void updateStatus();
293 void updateSelf();
294 void updatePhasers();
295 void updateShips();
296 void updatePlanets();
297 void updateTerrain();
298 void updateMessages();
299 void sendMissileNum();
300 extern void updateWarnings(); /* warning.c */
301 void sendClientSizedPacket();
302 void sendClientPacket();
303 void flushSockBuf();
304 void updateMOTD();
305 int parseQuery();
306 void bounce();
307 int gwrite();
308 void printUdpInfo();
309 int closeUdpConn();
310 void updateFat();
311 int fatten();
312 void fatMerge();
313 int doRead();
314 extern int read();
315 extern void perror();
316 void logmessage();
317 extern int ntorp();
318 extern int phaser();
319 extern int set_speed();
320 extern int set_course();
321 extern int shield_up();
322 extern int shield_down();
323 extern int repair();
324 extern int orbit();
325 extern pid_t fork();
326 extern int execl();
327 extern int bomb_planet();
328 extern int beam_up();
329 extern int beam_down();
330 extern int cloak_on();
331 extern int cloak_off();
332 extern void detothers();
333 extern void fire_missile_dir();
334 extern int nplasmatorp();
335 extern int lock_planet();
336 extern int lock_player();
337 extern int do_refit();
338 extern int pmessage2();
339 extern int parse_command_mess();
340 extern int write();
341 extern int setitimer();
342 extern int gethostname();
343 extern int decryptRSAPacket();
344 extern int makeRSAPacket();
345 extern int encryptReservedPacket();
346 void forceUpdate();
347 int connUdpConn();
348 extern int sendMotd();
349 void dequeue();
350 void enqueue();
351 extern int pmessage();
352
353 int
354 connectToClient(machine, port)
355 char *machine;
356 int port;
357 {
358 int ns;
359 struct sockaddr_in addr;
360 struct hostent *hp;
361 /* int len,cc; */
362 /* char buf[BUFSIZ]; */
363 /* int i; */
364
365 if (sock != -1)
366 {
367 shutdown(sock, 2);
368 sock = -1;
369 }
370 /* printf("Connecting to %s through %d\n", machine, port); */
371
372 if ((ns = socket(AF_INET, SOCK_STREAM, 0)) < 0)
373 {
374 printf("I cannot create a socket\n");
375 exit(2);
376 }
377 addr.sin_family = AF_INET;
378 addr.sin_port = htons(port);
379
380 if (remoteaddr != -1)
381 {
382 addr.sin_addr.s_addr = remoteaddr;
383 }
384 else if ((addr.sin_addr.s_addr = inet_addr(machine)) == -1)
385 {
386 if ((hp = gethostbyname(machine)) == NULL)
387 {
388 printf("I cannot get host name\n");
389 close(ns);
390 exit(1);
391 }
392 else
393 {
394 #if 1
395 memcpy((char *) &addr.sin_addr, hp->h_addr, hp->h_length);
396 #else
397 addr.sin_addr.s_addr = *(long *) hp->h_addr;
398 #endif
399 }
400 }
401 remoteaddr = addr.sin_addr.s_addr;
402
403 if (connect(ns, (struct sockaddr *) & addr, sizeof(addr)) < 0)
404 {
405 /* printf("I cannot connect through port %d\n", port); */
406 close(ns);
407 return (0);
408 }
409 sock = ns;
410 initClientData();
411 testtime = -1;
412 return (1);
413 }
414
415 /*
416 * Check the socket to read it's inet addr for possible future use.
417 */
418 void
419 checkSocket()
420 {
421 struct sockaddr_in sin;
422 int length;
423
424 length = sizeof(sin);
425 if (getpeername(sock, (struct sockaddr *) & sin, &length) < 0)
426 {
427 /* A bad thing. */
428 return;
429 }
430 remoteaddr = sin.sin_addr.s_addr;
431 }
432
433 void
434 initClientData()
435 /* invalidates all data, so it is all sent to the client */
436 {
437 int i;
438
439 clientDead = 0;
440 clientMissiles.num = 0;
441 for (i = 0; i < MAXPLAYER; i++)
442 {
443 clientHostile[i].hostile = -1;
444 clientStats[i].losses = -1;
445 clientLogin[i].rank = -1;
446 clientPlayersInfo[i].shiptype = -1;
447 clientPStatus[i].status = -1;
448 clientPlayers[i].x = htonl(-1);
449 clientPhasers[i].status = -1;
450 clientKills[i].kills = htonl(-1);
451 clientFlags[i].flags = htonl(-1);
452 mustUpdate[i] = 0;
453
454 fat_hostile[i].packet = (PTR) & clientHostile[i];
455 fat_hostile[i].pkt_size = sizeof(struct hostile_spacket);
456 fat_hostile[i].prev = fat_hostile[i].next = (FAT_NODE *) NULL;
457 fat_phaser[i].packet = (PTR) & clientPhasers[i];
458 fat_phaser[i].pkt_size = sizeof(struct phaser_spacket);
459 fat_phaser[i].prev = fat_phaser[i].next = (FAT_NODE *) NULL;
460 fat_kills[i].packet = (PTR) & clientKills[i];
461 fat_kills[i].pkt_size = sizeof(struct kills_spacket);
462 fat_kills[i].prev = fat_kills[i].next = (FAT_NODE *) NULL;
463 fat_flags[i].packet = (PTR) & clientFlags[i];
464 fat_flags[i].pkt_size = sizeof(struct flags_spacket);
465 fat_flags[i].prev = fat_flags[i].next = (FAT_NODE *) NULL;
466 }
467 for (i = 0; i < MAXPLAYER * MAXTORP; i++)
468 {
469 clientTorpsInfo[i].status = -1;
470 clientTorps[i].x = -1;
471
472 fat_torp_info[i].packet = (PTR) & clientTorpsInfo[i];
473 fat_torp_info[i].pkt_size = sizeof(struct torp_info_spacket);
474 fat_torp_info[i].prev = fat_torp_info[i].next = (FAT_NODE *) NULL;
475 }
476 for (i = 0; i < TOTALTHINGIES; i++)
477 {
478 clientThingysInfo[i].shape = htons(-1);
479 clientThingysInfo[i].owner = htons(i / NPTHINGIES);
480 clientThingys[i].x = htonl(-1);
481
482 fat_thingy_info[i].packet = (PTR) & clientThingysInfo[i];
483 fat_thingy_info[i].pkt_size = sizeof(struct torp_info_spacket);
484 fat_thingy_info[i].prev = fat_thingy_info[i].next = (FAT_NODE *) NULL;
485 }
486 for (i = 0; i < MAXPLAYER * MAXPLASMA; i++)
487 {
488 clientPlasmasInfo[i].status = -1;
489 clientPlasmas[i].x = -1;
490
491 fat_plasma_info[i].packet = (PTR) & clientPlasmasInfo[i];
492 fat_plasma_info[i].pkt_size = sizeof(struct plasma_info_spacket);
493 fat_plasma_info[i].prev = fat_plasma_info[i].next = (FAT_NODE *) NULL;
494 }
495 for (i = 0; i < MAXPLANETS; i++)
496 {
497 clientPlanets2[i].armies = htonl(-1);
498 clientPlanetLocs[i].x = htonl(-1);
499
500 #if 0
501 fat_planet[i].packet = (PTR) & clientPlanets[i];
502 fat_planet[i].pkt_size = sizeof(struct planet_spacket);
503 fat_planet[i].prev = fat_planet[i].next = (FAT_NODE *) NULL;
504 #else
505 fat_planet2[i].packet = (PTR) & clientPlanets2[i];
506 fat_planet2[i].pkt_size = sizeof(struct planet_spacket2);
507 fat_planet2[i].prev = fat_planet2[i].next = (FAT_NODE *) 0;
508 #endif
509 }
510 msgCurrent = (mctl->mc_current + 1) % MAXMESSAGE;
511 clientSelf.pnum = -1;
512
513 fat_you.packet = (PTR) & clientSelf;
514 fat_you.pkt_size = sizeof(struct you_spacket);
515 fat_you.prev = fat_you.next = (FAT_NODE *) NULL;
516 #if 0
517 fat_status.packet = (PTR) & clientStatus;
518 fat_status.pkt_size = sizeof(struct status_spacket);
519 fat_status.prev = fat_status.next = (FAT_NODE *) NULL;
520 #else
521 fat_status2.packet = (PTR) & clientStatus2;
522 fat_status2.pkt_size = sizeof(struct status_spacket2);
523 fat_status2.prev = fat_status2.next = (FAT_NODE *) 0;
524 #endif
525
526 reset_fat_list();
527 }
528
529 int
530 isClientDead()
531 {
532 return (clientDead);
533 }
534
535 void
536 updateClient()
537 {
538 int i;
539
540 for (i = 0; i < MAXPLAYER; i++)
541 {
542 mustUpdate[i] = 0;
543 }
544 updateShips();
545 #ifdef SHORT_PACKETS
546 if (send_short)
547 {
548 short_updateTorps();
549 }
550 else
551 #endif
552 {
553 updateTorps();
554 updateTorpInfos();
555 }
556
557 if (weaponsallowed[WP_MISSILE] ||
558 weaponsallowed[WP_FIGHTER])
559 updateMissiles();
560 updateThingies();
561 sendMissileNum(me->p_ship.s_missilestored);
562 updatePlasmas();
563 updateStatus();
564 updateSelf();
565 updatePhasers();
566 updatePlanets();
567 updateTerrain(); /* for galaxy reset */
568 updateMessages();
569 updateWarnings(); /* warning.c */
570
571 /*
572 * these checks are here to make sure we don't ping from the updateClient
573 * call in death(). The reason is that savestats() can take > 100ms,
574 * invalidating the next ping lag calc
575 */
576 /* Also, don't ping while in verification stage */
577
578 if (ping
579 && (repCount % efticks(5 * configvals->ping_period) == 0)
580 && me->p_status != PDEAD
581 && me->p_status != POUTFIT
582 /* && me->p_status != PTQUEUE */
583 #ifdef AUTHORIZE
584 && testtime <= 0
585 #endif
586 )
587 sendClientPing(); /* ping.c */
588
589 if (buffersEmpty())
590 {
591 /* We sent nothing! We better send something to wake him */
592 sendClientPacket((struct player_spacket *) & clientSelf);
593 }
594 flushSockBuf();
595 repCount++;
596 }
597
598 void
599 briefUpdateClient()
600 {
601 updateMessages();
602 updateMOTD();
603 updateWarnings();
604
605 flushSockBuf();
606 repCount++;
607 }
608
609 void
610 updateStatus()
611 {
612 if (repCount % efticks(75) == 0 &&
613 ((ntohl(clientStatus2.timeprod) != status->timeprod) ||
614 (clientStatus2.tourn != status->tourn)))
615 {
616 clientStatus2.type = SP_STATUS2;
617 clientStatus2.tourn = status->tourn;
618 clientStatus2.dooshes = htonl(status->dooshes);
619 clientStatus2.armsbomb = htonl(status->armsbomb);
620 clientStatus2.resbomb = htonl(status->resbomb);
621 clientStatus2.planets = htonl(status->planets);
622 clientStatus2.kills = htonl(status->kills);
623 clientStatus2.losses = htonl(status->losses);
624 clientStatus2.sbkills = htonl(status->sbkills);
625 clientStatus2.sblosses = htonl(status->sblosses);
626 clientStatus2.sbtime = htonl(status->sbtime);
627 clientStatus2.wbkills = htonl(status->wbkills);
628 clientStatus2.wblosses = htonl(status->wblosses);
629 clientStatus2.wbtime = htonl(status->wbtime);
630 clientStatus2.jsplanets = htonl(status->jsplanets);
631 clientStatus2.jstime = htonl(status->jstime);
632 clientStatus2.time = htonl(status->time);
633 clientStatus2.timeprod = htonl(status->timeprod);
634 sendClientPacket((struct player_spacket *) & clientStatus2);
635 }
636 }
637
638 struct player *
639 maybe_watching(p)
640 struct player *p;
641 {
642 struct player *tg = &players[me->p_playerl];
643 return (p == me
644 && me->p_status == POBSERVE
645 && (me->p_flags & PFPLOCK)
646 && (me->p_teamspy & tg->p_team)
647 && tg->p_spyable) ?
648 tg : p;
649 }
650
651 struct planet *
652 maybe_watching_planet()
653 {
654 return (me->p_status == POBSERVE && (me->p_flags & PFPLLOCK)) ?
655 &planets[me->p_planet] : 0;
656 }
657
658 void
659 updateSelf()
660 {
661 struct player *watched = maybe_watching(me);
662 int armies = maybe_watching_planet()
663 ? maybe_watching_planet()->pl_armies
664 : watched->p_armies;
665 int damage;
666
667 damage = watched->p_damage
668 + shipvals[watched->p_ship.s_type].s_maxdamage
669 - watched->p_ship.s_maxdamage;
670
671 if (ntohl(clientSelf.fuel) != watched->p_fuel ||
672 ntohl(clientSelf.shield) != watched->p_shield ||
673 ntohl(clientSelf.damage) != damage ||
674 ntohs(clientSelf.etemp) != watched->p_etemp ||
675 ntohs(clientSelf.wtemp) != watched->p_wtemp ||
676 ntohl(clientSelf.flags) != watched->p_flags ||
677 clientSelf.armies != armies ||
678 clientSelf.swar != watched->p_swar ||
679 ntohs(clientSelf.whydead) != watched->p_whydead ||
680 ntohs(clientSelf.whodead) != watched->p_whodead ||
681 clientSelf.pnum != me->p_no)
682 {
683
684 /* we want to send it, but how? */
685 clientSelf.type = SP_YOU;
686
687 if (commMode == COMM_UDP)
688 {
689 if (ntohl(clientSelf.flags) != watched->p_flags ||
690 clientSelf.armies != armies ||
691 clientSelf.swar != watched->p_swar)
692 {
693 clientSelf.type = SP_YOU | 0x40; /* mark as semi-critical */
694 }
695 if (ntohs(clientSelf.whydead) != watched->p_whydead ||
696 ntohs(clientSelf.whodead) != watched->p_whodead ||
697 clientSelf.pnum != me->p_no)
698 {
699 clientSelf.type = SP_YOU | 0x80; /* mark as critical */
700 }
701 }
702 clientSelf.pnum = me->p_no;
703 clientSelf.flags = htonl(watched->p_flags);
704 clientSelf.swar = watched->p_swar;
705 clientSelf.hostile = watched->p_hostile;
706 clientSelf.armies = armies;
707 clientSelf.shield = htonl(watched->p_shield);
708 clientSelf.fuel = htonl(watched->p_fuel);
709 clientSelf.etemp = htons(watched->p_etemp);
710 clientSelf.wtemp = htons(watched->p_wtemp);
711 clientSelf.whydead = htons(watched->p_whydead);
712 clientSelf.whodead = htons(watched->p_whodead);
713 clientSelf.damage = htonl(damage);
714 /* ATM - visible tractor */
715 clientSelf.tractor = (char) watched->p_tractor | 0x40;
716
717 clientSelf.pad2 = (unsigned char) (status->clock & 0xFF);
718 clientSelf.pad3 = (unsigned char) ((status->clock & 0xFF00) >> 8);
719 sendClientPacket((struct player_spacket *) & clientSelf);
720 }
721 }
722
723 extern int ignored[];
724
725 void
726 updateShips()
727 {
728 register int i;
729 register struct player *pl;
730 register struct plyr_info_spacket *cpli;
731 register struct player_spacket *cpl;
732 register struct kills_spacket *kills;
733 register struct flags_spacket *flags;
734 register struct pstatus_spacket *pstatus;
735 register struct plyr_login_spacket *login;
736 register struct hostile_spacket *hostile;
737 #if 0
738 struct stats_spacket ms_stats;
739 #endif
740 register struct stats_spacket2 *stats;
741 int update;
742 int x, y;
743 /*
744 * #define FLAGMASK
745 * (PFSHIELD|PFBOMB|PFORBIT|PFCLOAK|PFROBOT|PFBEAMUP|PFBEAMDOWN|PFPRACTR|PFD
746 * OCK|PFTRACT|PFPRESS|PFDOCKOK) atm mask
747 */
748
749 /*
750 * #define FLAGMASK
751 * (PFSHIELD|PFBOMB|PFORBIT|PFCLOAK|PFROBOT|PFBEAMUP|PFBEAMDOWN|PFPRACTR|PFD
752 * OCK|PFTRACT|PFPRESS|PFDOCKOK) aieee, too much. 7/27/91 TC
753 */
754
755 #define FLAGMASK (PFSHIELD|PFBOMB|PFORBIT|PFCLOAK|PFROBOT|PFPRACTR|PFDOCK|PFTRACT|PFPRESS|PFDOCKOK)
756 #define INVISOMASK (PFCLOAK|PFROBOT|PFPRACTR|PFDOCKOK)
757
758 /* Please excuse the ugliness of this loop declaration */
759 for (i = 0, pl = players, cpli = clientPlayersInfo, cpl = clientPlayers, kills = clientKills, flags = clientFlags, pstatus = clientPStatus, login = clientLogin, hostile = clientHostile, stats = clientStats2;
760 i < MAXPLAYER;
761 i++, pl++, cpli++, cpl++, kills++, flags++, pstatus++, login++, hostile++, stats++)
762 {
763 update = 0;
764 if (strcmp(pl->p_name, login->name) != 0 ||
765 pl->p_stats.st_rank != login->rank ||
766 strcmp(pl->p_monitor, login->monitor) != 0)
767 {
768 strncpy(login->name, pl->p_name, 15);
769 strncpy(login->monitor, pl->p_monitor, 15);
770 strncpy(login->login, pl->p_login, 15);
771 login->name[15] = 0;
772 login->monitor[15] = 0;
773 login->login[15] = 0;
774 login->type = SP_PL_LOGIN;
775 login->pnum = i;
776 login->rank = pl->p_stats.st_rank;
777 sendClientPacket((struct player_spacket *) login);
778 }
779 if ((pl != me && (pl->p_swar & me->p_team) != hostile->war) ||
780 (pl != me && (pl->p_hostile & me->p_team) != hostile->hostile) ||
781 (pl == me && pl->p_swar != hostile->war) ||
782 (pl == me && pl->p_hostile != hostile->hostile))
783 {
784 hostile->type = SP_HOSTILE;
785 if (pl == me)
786 {
787 hostile->war = pl->p_swar;
788 hostile->hostile = pl->p_hostile;
789 }
790 else
791 {
792 hostile->war = (pl->p_swar & me->p_team);
793 hostile->hostile = (pl->p_hostile & me->p_team);
794 }
795 hostile->pnum = i;
796 sendClientPacket((struct player_spacket *) hostile);
797 }
798 /*
799 * Send stat packets once per five updates. But, only send one. We will
800 * cycle through them all eventually.
801 */
802 /*
803 * Also, update if status chages (i.e., entered game, died, tq'ed, etc)
804 */
805
806 if (pl->p_status != pstatus->status ||
807 (repCount % (MAXPLAYER * efticks(5)) == i * efticks(5) &&
808 (stats->di != htonl(pl->p_stats.st_di) ||
809 stats->kills != htonl(pl->p_stats.st_tkills) ||
810 stats->losses != htonl(pl->p_stats.st_tlosses) ||
811 stats->armsbomb != htonl(pl->p_stats.st_tarmsbomb) ||
812 stats->resbomb != htonl(pl->p_stats.st_tresbomb) ||
813 stats->dooshes != htonl(pl->p_stats.st_tdooshes) ||
814 stats->planets != htonl(pl->p_stats.st_tplanets) ||
815 stats->sbkills != htonl(pl->p_stats.st_sbkills) ||
816 stats->sblosses != htonl(pl->p_stats.st_sblosses) ||
817 stats->wbkills != htonl(pl->p_stats.st_wbkills) ||
818 stats->wblosses != htonl(pl->p_stats.st_wblosses) ||
819 stats->jsplanets != htonl(pl->p_stats.st_jsplanets) ||
820 stats->rank != htonl(pl->p_stats.st_rank) ||
821 stats->royal != htonl(pl->p_stats.st_royal))))
822 {
823
824 stats->genocides = htonl(pl->p_stats.st_genocides);
825 stats->maxkills = htonl((int) (pl->p_stats.st_tmaxkills * 100));
826 stats->di = htonl((int) (pl->p_stats.st_di * 100));
827 stats->kills = htonl(pl->p_stats.st_tkills);
828 stats->losses = htonl(pl->p_stats.st_tlosses);
829 stats->armsbomb = htonl(pl->p_stats.st_tarmsbomb);
830 stats->resbomb = htonl(pl->p_stats.st_tresbomb);
831 stats->dooshes = htonl(pl->p_stats.st_tdooshes);
832 stats->planets = htonl(pl->p_stats.st_tplanets);
833 stats->tticks = htonl(pl->p_stats.st_tticks);
834 stats->sbkills = htonl(pl->p_stats.st_sbkills);
835 stats->sblosses = htonl(pl->p_stats.st_sblosses);
836 stats->sbticks = htonl(pl->p_stats.st_sbticks);
837 stats->sbmaxkills = htonl((int) (pl->p_stats.st_sbmaxkills * 100));
838 stats->wbkills = htonl(pl->p_stats.st_wbkills);
839 stats->wblosses = htonl(pl->p_stats.st_wblosses);
840 stats->wbticks = htonl(pl->p_stats.st_wbticks);
841 stats->wbmaxkills = htonl((int) (pl->p_stats.st_wbmaxkills * 100));
842 stats->jsplanets = htonl(pl->p_stats.st_jsplanets);
843 stats->jsticks = htonl(pl->p_stats.st_jsticks);
844 stats->rank = htonl(pl->p_stats.st_rank);
845 stats->royal = htonl(pl->p_stats.st_royal);
846 stats->type = SP_STATS2;
847 stats->pnum = i;
848 /* if (blk_metaserver == 0) */
849 sendClientPacket((struct player_spacket *) stats);
850 #if 0
851 else
852 {
853 ms_stats.type = SP_STATS;
854 ms_stats.pnum = i;
855 ms_stats.tkills = htonl(pl->p_stats.st_tkills);
856 ms_stats.tlosses = htonl(pl->p_stats.st_tlosses);
857 ms_stats.kills = htonl(1);
858 ms_stats.losses = htonl(1);
859 ms_stats.tticks = htonl(pl->p_stats.st_tticks);
860 ms_stats.tplanets = htonl(pl->p_stats.st_tplanets);
861 ms_stats.tarmies = htonl(pl->p_stats.st_tarmsbomb);
862 ms_stats.sbkills = htonl(pl->p_stats.st_sbkills);
863 ms_stats.sblosses = htonl(pl->p_stats.st_sblosses);
864 ms_stats.armies = htonl(1);
865 ms_stats.planets = htonl(1);
866 ms_stats.maxkills = htonl((long) (pl->p_stats.st_tmaxkills * 100));
867 ms_stats.sbmaxkills = htonl((long) (pl->p_stats.st_sbmaxkills * 100));
868 sendClientPacket((struct player_spacket *) & ms_stats);
869 }
870 #endif
871 }
872 if (maybe_watching(pl)->p_ship.s_type != cpli->shiptype ||
873 pl->p_team != cpli->team)
874 {
875 cpli->type = SP_PLAYER_INFO;
876 cpli->pnum = i;
877 cpli->shiptype = maybe_watching(pl)->p_ship.s_type;
878 cpli->team = pl->p_team;
879 sendClientPacket((struct player_spacket *) cpli);
880 /*
881 * if (!blk_flag) cpli->shiptype=pl->p_ship.s_type;
882 */
883 }
884 if (kills->kills != htonl((int) (maybe_watching(pl)->p_kills * 100)))
885 {
886 kills->type = SP_KILLS;
887 kills->pnum = i;
888 kills->kills = htonl((int) (maybe_watching(pl)->p_kills * 100));
889 sendClientPacket((struct player_spacket *) kills);
890 }
891 {
892 int plstat = pl->p_status;
893
894 #ifdef LEAGUE_SUPPORT
895 if (status2->paused && pl->p_team != me->p_team)
896 plstat = PFREE; /* enemies are invisible when the game is
897 * paused */
898 #endif
899
900 if (pstatus->status != plstat)
901 {
902 /*
903 * We update the location of people whose status has changed. (like
904 * if they just re-entered...)
905 */
906 update = 1;
907 pstatus->type = SP_PSTATUS;
908 pstatus->pnum = i;
909 pstatus->status = plstat;
910 if (pl->p_status == PFREE)
911 {
912 /*
913 * I think this will turn off ignores for players that leave.
914 * 7/24/91 TC
915 */
916 ignored[i] = 0;
917 }
918 sendClientPacket((struct player_spacket *) pstatus);
919 }
920 }
921
922 /* Used to send flags here, see below 8/7/91 TC */
923
924 if (!configvals->hiddenenemy || pl->p_team == me->p_team ||
925 (maybe_watching(pl)->p_flags & PFSEEN) || (status->tourn == 0) ||
926 (maybe_watching(pl)->p_flags & PFROBOT))
927 { /* a bot never has its PFSEEN bit set */
928
929 x = maybe_watching(pl)->p_x;
930 y = maybe_watching(pl)->p_y;
931 if (me != pl && flags->flags !=
932 htonl(FLAGMASK & maybe_watching(pl)->p_flags))
933 {
934 flags->type = SP_FLAGS;
935 flags->pnum = i;
936 flags->flags = htonl(FLAGMASK & maybe_watching(pl)->p_flags);
937 flags->tractor = (char) maybe_watching(pl)->p_tractor | 0x40; /* ATM - visible tractor */
938 sendClientPacket((struct player_spacket *) flags);
939 }
940 }
941 else
942 {
943 /* A hack to make him inviso */
944 x = -100000;
945 y = -100000;
946
947 /* reduce flag info if he's inviso 8/7/91 TC */
948
949 if (me != pl && flags->flags != htonl(INVISOMASK & pl->p_flags))
950 {
951 flags->type = SP_FLAGS;
952 flags->pnum = i;
953 flags->flags = htonl(INVISOMASK & pl->p_flags);
954 sendClientPacket((struct player_spacket *) flags);
955 }
956 }
957 if (x != ntohl(cpl->x) || y != ntohl(cpl->y) ||
958 maybe_watching(pl)->p_dir != cpl->dir ||
959 maybe_watching(pl)->p_speed != cpl->speed)
960 {
961 /*
962 * We update the player if: 1) haven't updated him for 9 intervals. 2)
963 * he is on the screen 3) he was on the screen recently.
964 */
965 if (!update && repCount % efticks(9) != 0 &&
966 (ntohl(cpl->x) < me->p_x - SCALE * WINSIDE / 2 ||
967 ntohl(cpl->x) > me->p_x + SCALE * WINSIDE / 2 ||
968 ntohl(cpl->y) > me->p_y + SCALE * WINSIDE / 2 ||
969 ntohl(cpl->y) < me->p_y - SCALE * WINSIDE / 2) &&
970 (y > me->p_y + SCALE * WINSIDE / 2 ||
971 x > me->p_x + SCALE * WINSIDE / 2 ||
972 x < me->p_x - SCALE * WINSIDE / 2 ||
973 y < me->p_y - SCALE * WINSIDE / 2))
974 continue;
975 /*
976 * If the guy is cloaked, give information only occasionally, and make
977 * it slightly inaccurate. Also, we don't give a direction. The client
978 * has no reason to know.
979 */
980 if ((pl->p_flags & PFCLOAK) &&
981 (pl->p_cloakphase == (CLOAK_PHASES - 1)) &&
982 (maybe_watching(me) != pl) && !mustUpdate[i])
983 {
984 if (repCount % efticks(9) != 0)
985 continue;
986 cpl->type = SP_PLAYER;
987 cpl->pnum = i;
988 cpl->x = htonl(x + (lrand48() % 2000) - 1000);
989 cpl->y = htonl(y + (lrand48() % 2000) - 1000);
990 sendClientPacket(cpl);
991 continue;
992 }
993 cpl->type = SP_PLAYER;
994 cpl->pnum = i;
995 cpl->x = htonl(x);
996 cpl->y = htonl(y);
997 cpl->speed = maybe_watching(pl)->p_speed;
998 cpl->dir = maybe_watching(pl)->p_dir;
999 sendClientPacket(cpl);
1000 }
1001 }
1002 }
1003
1004 void
1005 updateTorpInfos()
1006 {
1007 register struct torp *torp;
1008 register int i;
1009 register struct torp_info_spacket *tpi;
1010
1011 for (i = 0, torp = torps, tpi = clientTorpsInfo;
1012 i < MAXPLAYER * MAXTORP;
1013 i++, torp++, tpi++)
1014 {
1015 if (torp->t_owner == me->p_no)
1016 {
1017 if (torp->t_war != tpi->war ||
1018 torp->t_status != tpi->status)
1019 {
1020 tpi->type = SP_TORP_INFO;
1021 tpi->war = torp->t_war;
1022 tpi->status = torp->t_status;
1023 tpi->tnum = htons(i);
1024 sendClientPacket((struct player_spacket *) tpi);
1025 }
1026 }
1027 else
1028 { /* Someone else's torp... */
1029 if (torp->t_y > me->p_y + SCALE * WINSIDE / 2 ||
1030 torp->t_x > me->p_x + SCALE * WINSIDE / 2 ||
1031 torp->t_x < me->p_x - SCALE * WINSIDE / 2 ||
1032 torp->t_y < me->p_y - SCALE * WINSIDE / 2 ||
1033 torp->t_status == TFREE)
1034 {
1035 if (torp->t_status == TFREE && tpi->status == TEXPLODE)
1036 {
1037 tpi->status = TFREE;
1038 continue;
1039 }
1040 if (tpi->status != TFREE)
1041 {
1042 tpi->status = TFREE;
1043 tpi->tnum = htons(i);
1044 tpi->type = SP_TORP_INFO;
1045 sendClientPacket((struct player_spacket *) tpi);
1046 }
1047 }
1048 else
1049 { /* in view */
1050 enum torp_status_e tstatus = torp->t_status;
1051
1052 #ifdef LEAGUE_SUPPORT
1053 if (status2->paused
1054 && players[torp->t_owner].p_team != me->p_team)
1055 tstatus = TFREE; /* enemy torps are invisible during game
1056 * pause */
1057 #endif
1058
1059 if (tstatus != tpi->status ||
1060 (torp->t_war & me->p_team) != tpi->war)
1061 {
1062 /* Let the client fade away the explosion on its own */
1063 tpi->war = torp->t_war & me->p_team;
1064 tpi->type = SP_TORP_INFO;
1065 tpi->tnum = htons(i);
1066 tpi->status = tstatus;
1067 sendClientPacket((struct player_spacket *) tpi);
1068 }
1069 }
1070 }
1071 }
1072 }
1073
1074
1075
1076 void
1077 updateTorps()
1078 {
1079 register struct torp *torp;
1080 register int i;
1081 register struct torp_spacket *tp;
1082
1083 for (i = 0, torp = torps, tp = clientTorps;
1084 i < MAXPLAYER * MAXTORP;
1085 i++, torp++, tp++)
1086 {
1087 if (torp->t_owner == me->p_no)
1088 {
1089
1090 if (tp->x != htonl(torp->t_x) ||
1091 tp->y != htonl(torp->t_y))
1092 {
1093 tp->type = SP_TORP;
1094 tp->x = htonl(torp->t_x);
1095 tp->y = htonl(torp->t_y);
1096 tp->dir = torp->t_dir;
1097 tp->tnum = htons(i);
1098 sendClientPacket((struct player_spacket *) tp);
1099 }
1100 }
1101 else
1102 { /* Someone else's torp... */
1103 if (torp->t_y > me->p_y + SCALE * WINSIDE / 2 ||
1104 torp->t_x > me->p_x + SCALE * WINSIDE / 2 ||
1105 torp->t_x < me->p_x - SCALE * WINSIDE / 2 ||
1106 torp->t_y < me->p_y - SCALE * WINSIDE / 2 ||
1107 torp->t_status == TFREE)
1108 {
1109 /* do nothing */
1110 }
1111 else
1112 { /* in view */
1113 enum torp_status_e tstatus = torp->t_status;
1114
1115 #ifdef LEAGUE_SUPPORT
1116 if (status2->paused
1117 && players[torp->t_owner].p_team != me->p_team)
1118 tstatus = TFREE; /* enemy torps are invisible during game
1119 * pause */
1120 #endif
1121
1122 if (tstatus == TFREE)
1123 continue; /* no need to transmit position */
1124
1125 if (tp->x != htonl(torp->t_x) ||
1126 tp->y != htonl(torp->t_y))
1127 {
1128 tp->x = htonl(torp->t_x);
1129 tp->y = htonl(torp->t_y);
1130 tp->dir = torp->t_dir;
1131 tp->tnum = htons(i);
1132 tp->type = SP_TORP;
1133 sendClientPacket((struct player_spacket *) tp);
1134 }
1135 }
1136 }
1137 }
1138 }
1139
1140 #ifdef SHORT_PACKETS
1141
1142 #define NIBBLE() *(*data)++ = (torp->t_war & 0xf) | (torp->t_status << 4)
1143
1144 int
1145 encode_torp_status(torp, pnum, data, tpi, tp, mustsend)
1146 struct torp *torp;
1147 int pnum;
1148 char **data;
1149 struct torp_info_spacket *tpi;
1150 struct torp_spacket *tp;
1151 int *mustsend;
1152 {
1153 if (pnum != me->p_no)
1154 {
1155 int dx, dy;
1156 int i = SCALE * WINSIDE / 2;
1157 dx = me->p_x - torp->t_x;
1158 dy = me->p_y - torp->t_y;
1159 if (dx < -i || dx > i || dy < -i || dy > i || torp->t_status == TFREE)
1160 {
1161 if (torp->t_status == TFREE && tpi->status == TEXPLODE)
1162 tpi->status = TFREE;
1163 else if (tpi->status != TFREE)
1164 {
1165 tpi->status = TFREE;
1166 *mustsend = 1;
1167 }
1168 return 0;
1169 }
1170 }
1171
1172 if (torp->t_war != tpi->war)
1173 {
1174 tpi->war = torp->t_war;
1175 tpi->status = torp->t_status;
1176 NIBBLE();
1177 return 1;
1178 }
1179 else if (torp->t_status != tpi->status)
1180 {
1181 switch (torp->t_status)
1182 {
1183 case TFREE:
1184 {
1185 int rval = 0;
1186 if (tpi->status == TEXPLODE)
1187 {
1188 NIBBLE();
1189 rval = 1;
1190 }
1191 else
1192 *mustsend = 1;
1193 tpi->status = torp->t_status;
1194 tp->x = htonl(torp->t_x);
1195 tp->y = htonl(torp->t_y);
1196 return rval;
1197 }
1198 break;
1199 case TMOVE:
1200 case TSTRAIGHT:
1201 tpi->status = torp->t_status;
1202 break;
1203 default:
1204 NIBBLE();
1205 tpi->status = torp->t_status;
1206 return 1;
1207 break;
1208 }
1209 }
1210 return 0;
1211 }
1212
1213 #define TORP_INVISIBLE(tstatus) ( \
1214 (tstatus)== TFREE || \
1215 (tstatus) == TOFF || \
1216 (tstatus) == TLAND)
1217
1218 int
1219 encode_torp_position(torp, pnum, data, shift, cache)
1220 struct torp *torp;
1221 int pnum;
1222 char **data;
1223 int *shift;
1224 struct torp_spacket *cache;
1225 {
1226 int x, y;
1227
1228 if (htonl(torp->t_x) == cache->x &&
1229 htonl(torp->t_y) == cache->y)
1230 return 0;
1231
1232 cache->x = htonl(torp->t_x);
1233 cache->y = htonl(torp->t_y);
1234
1235 if (TORP_INVISIBLE(torp->t_status)
1236 #ifdef LEAGUE_SUPPORT
1237 || (status2->paused &&
1238 players[pnum].p_team != me->p_team)
1239 #endif
1240 )
1241 return 0;
1242
1243 x = torp->t_x / SCALE - me->p_x / SCALE + WINSIDE / 2;
1244 y = torp->t_y / SCALE - me->p_y / SCALE + WINSIDE / 2;
1245
1246 if (x < 0 || x >= WINSIDE ||
1247 y < 0 || y >= WINSIDE)
1248 {
1249 if (pnum != me->p_no)
1250 return 0;
1251 x = y = 501;
1252 }
1253
1254 **data |= x << *shift;
1255 *(++(*data)) = (0x1ff & x) >> (8 - *shift);
1256 (*shift)++;
1257 **data |= y << *shift;
1258 *(++(*data)) = (0x1ff & y) >> (8 - *shift);
1259 (*shift)++;
1260 if (*shift == 8)
1261 {
1262 *shift = 0;
1263 *(++(*data)) = 0;
1264 }
1265 return 1;
1266 }
1267
1268 void
1269 short_updateTorps()
1270 {
1271 register int i;
1272
1273 for (i = 0; i <= (MAXPLAYER * MAXTORP - 1) / 8; i++)
1274 {
1275 struct torp *torp = &torps[i * 8];
1276 int j;
1277 char packet[2 /* packet type and player number */
1278 + 1 /* torp mask */
1279 + 1 /* torp info mask */
1280 + 18 /* 2*8 9-bit numbers */
1281 + 8 /* 8 torp info bytes */
1282 ];
1283 char *data = packet + 4;
1284 char info[8];
1285 char *ip = info;
1286 int shift = 0;
1287 int torppos_mask = 0;
1288 int torpinfo_mask = 0;
1289 int mustsend;
1290
1291 /* encode screen x and y coords */
1292 data[0] = 0;
1293 #define TIDX (j+i*8)
1294 #define PNUM ((int)((j+i*8)/MAXTORP))
1295 for (j = 0; j < 8 && TIDX < MAXPLAYER * MAXTORP; j++)
1296 {
1297 torpinfo_mask |= encode_torp_status
1298 (&torp[j], PNUM, &ip, &clientTorpsInfo[TIDX], &clientTorps[TIDX], &mustsend) << j;
1299 torppos_mask |= encode_torp_position
1300 (&torp[j], PNUM, &data, &shift, &clientTorps[TIDX]) << j;
1301 }
1302
1303 /*
1304 * if (!torppos_mask) continue;
1305 */
1306
1307 if (torpinfo_mask)
1308 {
1309 if (shift)
1310 data++;
1311 for (j = 0; j < 8 && &info[j] < ip; j++)
1312 data[j] = info[j];
1313 packet[0] = SP_S_TORP_INFO;
1314 packet[1] = torppos_mask;
1315 packet[2] = i;
1316 packet[3] = torpinfo_mask;
1317 sendClientSizedPacket(packet, (data - packet + j));
1318 }
1319 else if (torppos_mask == 0xff)
1320 {
1321 /* what a disgusting hack */
1322 packet[2] = SP_S_8_TORP;
1323 packet[3] = i;
1324 sendClientSizedPacket(packet + 2, 20);
1325 }
1326 else if (mustsend || torppos_mask != 0)
1327 {
1328 packet[1] = SP_S_TORP;
1329 packet[2] = torppos_mask & 0xff;
1330 packet[3] = i;
1331 sendClientSizedPacket(packet + 1, (data - (packet + 1) + (shift != 0)));
1332 }
1333 }
1334 #undef PNUM
1335 #undef TIDX
1336 }
1337
1338
1339 #endif
1340
1341
1342 void
1343 updateMissiles()
1344 {
1345 register struct missile *missile;
1346 register int i;
1347 register struct thingy_info_spacket *dpi;
1348 register struct thingy_spacket *dp;
1349
1350 for (i = 0, missile = missiles, dpi = clientThingysInfo, dp = clientThingys;
1351 i < MAXPLAYER * NPTHINGIES;
1352 i++, missile++, dpi++, dp++)
1353 {
1354 enum torp_status_e msstatus = missile->ms_status;
1355
1356 #ifdef LEAGUE_SUPPORT
1357 if (status2->paused &&
1358 players[missile->ms_owner].p_team != me->p_team)
1359 msstatus = TFREE; /* enemy torps are invisible during game
1360 * pause */
1361 #endif
1362
1363 switch (msstatus)
1364 {
1365 case TFREE:
1366 case TLAND:
1367 case TOFF:
1368 dpi->shape = htons(SHP_BLANK);
1369 break;
1370 case TMOVE:
1371 case TRETURN:
1372 case TSTRAIGHT:
1373 dpi->shape = htons((missile->ms_type == FIGHTERTHINGY)
1374 ? SHP_FIGHTER
1375 : SHP_MISSILE);
1376 break;
1377 case TEXPLODE:
1378 case TDET:
1379 dpi->shape = htons(SHP_PBOOM);
1380 break;
1381 }
1382
1383 dpi->type = SP_THINGY_INFO;
1384 dpi->tnum = htons(i);
1385
1386 dp->type = SP_THINGY;
1387 dp->tnum = htons(i);
1388 dp->dir = missile->ms_dir;
1389
1390 if (missile->ms_owner == me->p_no)
1391 {
1392 if (missile->ms_war != dpi->war ||
1393 msstatus != clientThingyStatus[i])
1394 {
1395 dpi->war = missile->ms_war;
1396 clientThingyStatus[i] = msstatus;
1397 sendClientPacket((struct player_spacket *) dpi);
1398 }
1399 if (dp->x != htonl(missile->ms_x) ||
1400 dp->y != htonl(missile->ms_y))
1401 {
1402 dp->x = htonl(missile->ms_x);
1403 dp->y = htonl(missile->ms_y);
1404 /* printf("missile at %d,%d\n", dp->x, dp->y); */
1405 sendClientPacket((struct player_spacket *) dp);
1406 }
1407 }
1408 else
1409 { /* Someone else's missile... */
1410 if (msstatus == TFREE ||
1411 missile->ms_y > me->p_y + SCALE * WINSIDE / 2 ||
1412 missile->ms_x > me->p_x + SCALE * WINSIDE / 2 ||
1413 missile->ms_x < me->p_x - SCALE * WINSIDE / 2 ||
1414 missile->ms_y < me->p_y - SCALE * WINSIDE / 2)
1415 {
1416 if (msstatus == TFREE && clientThingyStatus[i] == TEXPLODE)
1417 {
1418 clientThingyStatus[i] = TFREE;
1419 continue;
1420 }
1421 if (clientThingyStatus[i] != TFREE)
1422 {
1423 clientThingyStatus[i] = TFREE;
1424 dpi->shape = htons(SHP_BLANK);
1425 sendClientPacket((struct player_spacket *) dpi);
1426 }
1427 }
1428 else
1429 { /* in view */
1430 if (dp->x != htonl(missile->ms_x) ||
1431 dp->y != htonl(missile->ms_y))
1432 {
1433 dp->x = htonl(missile->ms_x);
1434 dp->y = htonl(missile->ms_y);
1435 sendClientPacket((struct player_spacket *) dp);
1436 }
1437 if (msstatus != clientThingyStatus[i] ||
1438 (missile->ms_war & me->p_team) != dpi->war)
1439 {
1440 /* Let the client fade away the explosion on its own */
1441 dpi->war = missile->ms_war & me->p_team;
1442 clientThingyStatus[i] = msstatus;
1443 sendClientPacket((struct player_spacket *) dpi);
1444 }
1445 }
1446 }
1447 }
1448 }
1449
1450 static void
1451 fill_thingy_info_packet(thing, packet)
1452 struct thingy *thing;
1453 struct thingy_info_spacket *packet;
1454 {
1455 switch (thing->type)
1456 {
1457 case TT_NONE:
1458 packet->war = 0;
1459 packet->shape = htons(SHP_BLANK);
1460 packet->owner = 0;
1461 break;
1462 case TT_WARP_BEACON:
1463 packet->war = 0;
1464 if (thing->u.wbeacon.owner == me->p_team)
1465 {
1466 packet->shape = htons(SHP_WARP_BEACON);
1467 packet->owner = htons(thing->u.wbeacon.owner);
1468 }
1469 else
1470 {
1471 packet->shape = htons(SHP_BLANK);
1472 packet->owner = 0;
1473 }
1474 break;
1475 default:
1476 printf("Unknown thingy type: %d\n", (int) thing->type);
1477 break;
1478 }
1479 }
1480
1481 static void
1482 fill_thingy_packet(thing, packet)
1483 struct thingy *thing;
1484 struct thingy_spacket *packet;
1485 {
1486 switch (thing->type)
1487 {
1488 case TT_NONE:
1489 packet->dir = 0;
1490 packet->x = packet->y = htonl(0);
1491 break;
1492 case TT_WARP_BEACON:
1493 packet->dir = 0;
1494 if (thing->u.wbeacon.owner == me->p_team)
1495 {
1496 packet->x = htonl(thing->u.wbeacon.x);
1497 packet->y = htonl(thing->u.wbeacon.y);
1498 }
1499 else
1500 {
1501 packet->x = packet->y = htonl(0);
1502 }
1503 break;
1504 default:
1505 printf("Unknown thingy type: %d\n", (int) thing->type);
1506 break;
1507 }
1508 }
1509
1510 void
1511 updateThingies()
1512 {
1513 struct thingy *thing;
1514 struct thingy_info_spacket *tip;
1515 struct thingy_spacket *tp;
1516 int i;
1517
1518 for (i = 0; i < NGTHINGIES; i++)
1519 {
1520 struct thingy_info_spacket ti1;
1521 struct thingy_spacket t2;
1522
1523 thing = &thingies[i];
1524 tip = &clientThingysInfo[i + MAXPLAYER * NPTHINGIES];
1525 tp = &clientThingys[i + MAXPLAYER * NPTHINGIES];
1526
1527 ti1.type = SP_THINGY_INFO;
1528 ti1.tnum = htons(i + MAXPLAYER * NPTHINGIES);
1529 fill_thingy_info_packet(thing, &ti1);
1530
1531 if (0 != memcmp((char *) tip, (char *) &ti1, sizeof(ti1)))
1532 {
1533 memcpy(tip, &ti1, sizeof(ti1));
1534 sendClientPacket((struct player_spacket *) tip);
1535 }
1536
1537 if (tip->shape != htons(SHP_BLANK))
1538 {
1539 t2.type = SP_THINGY;
1540 t2.tnum = htons(i + MAXPLAYER * NPTHINGIES);
1541 fill_thingy_packet(thing, &t2);
1542
1543 if (0 != memcmp(tp, &t2, sizeof(t2)))
1544 {
1545 memcpy(tp, &t2, sizeof(t2));
1546 sendClientPacket((struct player_spacket *) tp);
1547 }
1548 }
1549 }
1550
1551 }
1552
1553 void
1554 updatePlasmas()
1555 {
1556 register struct plasmatorp *torp;
1557 register int i;
1558 register struct plasma_info_spacket *tpi;
1559 register struct plasma_spacket *tp;
1560
1561 for (i = 0, torp = plasmatorps, tpi = clientPlasmasInfo, tp = clientPlasmas;
1562 i < MAXPLAYER * MAXPLASMA;
1563 i++, torp++, tpi++, tp++)
1564 {
1565 if (torp->pt_owner == me->p_no)
1566 {
1567 if (torp->pt_war != tpi->war ||
1568 torp->pt_status != tpi->status)
1569 {
1570 tpi->type = SP_PLASMA_INFO;
1571 tpi->war = torp->pt_war;
1572 tpi->status = torp->pt_status;
1573 tpi->pnum = htons(i);
1574 sendClientPacket((struct player_spacket *) tpi);
1575 }
1576 if (tp->x != htonl(torp->pt_x) ||
1577 tp->y != htonl(torp->pt_y))
1578 {
1579 tp->type = SP_PLASMA;
1580 tp->x = htonl(torp->pt_x);
1581 tp->y = htonl(torp->pt_y);
1582 tp->pnum = htons(i);
1583 sendClientPacket((struct player_spacket *) tp);
1584 }
1585 }
1586 else
1587 { /* Someone else's torp... */
1588 enum torp_status_e ptstatus = torp->pt_status;
1589
1590 #ifdef LEAGUE_SUPPORT
1591 if (status2->paused &&
1592 players[torp->pt_owner].p_team != me->p_team)
1593 ptstatus = TFREE; /* enemy torps are invisible during game
1594 * pause */
1595 #endif
1596 if (torp->pt_y > me->p_y + SCALE * WINSIDE / 2 ||
1597 torp->pt_x > me->p_x + SCALE * WINSIDE / 2 ||
1598 torp->pt_x < me->p_x - SCALE * WINSIDE / 2 ||
1599 torp->pt_y < me->p_y - SCALE * WINSIDE / 2 ||
1600 ptstatus == PTFREE)
1601 {
1602 if (ptstatus == PTFREE && tpi->status == PTEXPLODE)
1603 {
1604 tpi->status = PTFREE;
1605 continue;
1606 }
1607 if (tpi->status != PTFREE)
1608 {
1609 tpi->status = PTFREE;
1610 tpi->pnum = htons(i);
1611 tpi->type = SP_PLASMA_INFO;
1612 sendClientPacket((struct player_spacket *) tpi);
1613 }
1614 }
1615 else
1616 { /* in view */
1617 /* Send torp (we assume it moved) */
1618 tp->x = htonl(torp->pt_x);
1619 tp->y = htonl(torp->pt_y);
1620 tp->pnum = htons(i);
1621 tp->type = SP_PLASMA;
1622 sendClientPacket((struct player_spacket *) tp);
1623 if (ptstatus != tpi->status ||
1624 (torp->pt_war & me->p_team) != tpi->war)
1625 {
1626 tpi->war = torp->pt_war & me->p_team;
1627 tpi->type = SP_PLASMA_INFO;
1628 tpi->pnum = htons(i);
1629 tpi->status = ptstatus;
1630 sendClientPacket((struct player_spacket *) tpi);
1631 }
1632 }
1633 }
1634 }
1635 }
1636
1637 void
1638 updatePhasers()
1639 {
1640 register int i;
1641 register struct phaser_spacket *ph;
1642 register struct phaser *phase;
1643 register struct player *pl;
1644
1645 for (i = 0, ph = clientPhasers, phase = phasers, pl = players;
1646 i < MAXPLAYER; i++, ph++, phase++, pl++)
1647 {
1648 if (pl->p_y > me->p_y + SCALE * WINSIDE / 2 ||
1649 pl->p_x > me->p_x + SCALE * WINSIDE / 2 ||
1650 pl->p_x < me->p_x - SCALE * WINSIDE / 2 ||
1651 pl->p_y < me->p_y - SCALE * WINSIDE / 2)
1652 {
1653 if (ph->status != PHFREE)
1654 {
1655 ph->pnum = i;
1656 ph->type = SP_PHASER;
1657 ph->status = PHFREE;
1658 sendClientPacket((struct player_spacket *) ph);
1659 }
1660 }
1661 else
1662 {
1663 if (phase->ph_status == PHHIT)
1664 {
1665 mustUpdate[phase->ph_target] = 1;
1666 }
1667 if (ph->status != phase->ph_status ||
1668 ph->dir != phase->ph_dir ||
1669 ph->target != htonl(phase->ph_target))
1670 {
1671 ph->pnum = i;
1672 ph->type = SP_PHASER;
1673 ph->status = phase->ph_status;
1674 ph->dir = phase->ph_dir;
1675 ph->x = htonl(phase->ph_x);
1676 ph->y = htonl(phase->ph_y);
1677 ph->target = htonl(phase->ph_target);
1678 sendClientPacket((struct player_spacket *) ph);
1679 }
1680 }
1681 }
1682 }
1683
1684
1685 #define PLFLAGMASK (PLRESMASK|PLATMASK|PLSURMASK|PLPARADISE|PLTYPEMASK)
1686
1687 void
1688 updatePlanets()
1689 {
1690 register int i;
1691 register struct planet *plan;
1692 register struct planet_loc_spacket *pll;
1693 #if 0
1694 register struct planet_spacket *mspl;
1695 #endif
1696 register struct planet_spacket2 *pl;
1697 int dx, dy;
1698 int d2x, d2y;
1699 char *name;
1700
1701 for (i = 0, pl = clientPlanets2, plan = planets, pll = clientPlanetLocs;
1702 i < MAXPLANETS;
1703 i++, pl++, plan++, pll++)
1704 {
1705 /*
1706 * Send him info about him not having info if he doesn't but thinks he
1707 * does. Also send him info on every fifth cycle if the planet needs to
1708 * be redrawn.
1709 */
1710 if (((plan->pl_hinfo & me->p_team) == 0) && (pl->info & me->p_team))
1711 {
1712 pl->type = SP_PLANET2;
1713 pl->pnum = i;
1714 pl->info = 0;
1715 pl->flags = PLPARADISE;
1716 sendClientPacket((struct player_spacket *) pl);
1717 }
1718 else
1719 {
1720 struct teaminfo temp, *ptr;
1721 if (configvals->durablescouting)
1722 {
1723 temp.owner = plan->pl_owner;
1724 temp.armies = plan->pl_armies;
1725 temp.flags = plan->pl_flags;
1726 temp.timestamp = status->clock;
1727 ptr = &temp;
1728 }
1729 else
1730 ptr = &plan->pl_tinfo[me->p_team];
1731
1732 if (pl->info != plan->pl_hinfo ||
1733 pl->armies != htonl(ptr->armies) ||
1734 pl->owner != ptr->owner ||
1735 pl->flags != htonl(ptr->flags & PLFLAGMASK)
1736 || ((pl->timestamp != htonl(ptr->timestamp))
1737 && (me->p_team != plan->pl_owner)))
1738 {
1739 pl->type = SP_PLANET2;
1740 pl->pnum = (char) i;
1741 pl->info = (char) plan->pl_hinfo;
1742 pl->flags = htonl(ptr->flags & PLFLAGMASK);
1743 pl->armies = htonl(ptr->armies);
1744 pl->owner = (char) ptr->owner;
1745 pl->timestamp = htonl(ptr->timestamp);
1746 sendClientPacket((struct player_spacket *) pl);
1747 }
1748 }
1749 /* Assume that the planet only needs to be updated once... */
1750
1751 /* Odd, changes in pl_y not supported. 5/31/92 TC */
1752
1753 dx = ntohl(pll->x) - plan->pl_x;
1754 if (dx < 0)
1755 dx = -dx;
1756 dy = ntohl(pll->y) - plan->pl_y;
1757 if (dy < 0)
1758 dy = -dy;
1759
1760 d2x = plan->pl_x - me->p_x;
1761 d2y = plan->pl_y - me->p_y;
1762 if (d2x < 0)
1763 d2x = -d2x;
1764 if (d2y < 0)
1765 d2y = -d2y;
1766
1767 if (1 || plan->pl_hinfo & me->p_team)
1768 name = plan->pl_name;
1769 else
1770 name = " ";
1771 /*
1772 * if ((pll->x != htonl(plan->pl_x)) || (pll->y != htonl(plan->pl_y))) {
1773 */
1774 if (strcmp(pll->name, name) ||
1775 ((dx > 400 || dy > 400) ||
1776 ((dx >= 20 || dy >= 20) && (d2x < 10000 && d2y < 10000))))
1777 {
1778 pll->x = htonl(plan->pl_x);
1779 pll->y = htonl(plan->pl_y);
1780 pll->pnum = i;
1781 if (plan->pl_system == 0)
1782 pll->pad2 = 255;
1783 else
1784 pll->pad2 = (char) stars[plan->pl_system];
1785 strcpy(pll->name, name);
1786 pll->type = SP_PLANET_LOC;
1787 sendClientPacket((struct player_spacket *) pll);
1788 }
1789 }
1790 }
1791
1792 void
1793 updateMessages()
1794 {
1795 int i;
1796 struct message *cur;
1797 struct mesg_spacket msg;
1798
1799 for (i = msgCurrent; i != (mctl->mc_current + 1) % MAXMESSAGE; i = (i + 1) % MAXMESSAGE)
1800 {
1801 if (i == MAXMESSAGE)
1802 i = 0;
1803 cur = &messages[i];
1804
1805 if (cur->m_flags & MVALID &&
1806 (cur->m_flags & MALL ||
1807 (cur->m_flags & MTEAM && cur->m_recpt == me->p_team) ||
1808 (cur->m_flags & MINDIV && cur->m_recpt == me->p_no) ||
1809 (cur->m_flags & MGOD && cur->m_from == me->p_no)))
1810 {
1811 msg.type = SP_MESSAGE;
1812 strncpy(msg.mesg, cur->m_data, 80);
1813 msg.mesg[79] = '\0';
1814 msg.m_flags = cur->m_flags;
1815 msg.m_recpt = cur->m_recpt;
1816 msg.m_from = cur->m_from;
1817
1818 if ((cur->m_from < 0)
1819 || (cur->m_from > MAXPLAYER)
1820 || (cur->m_flags & MGOD && cur->m_from == me->p_no)
1821 || (cur->m_flags & MALL && !(ignored[cur->m_from] & MALL))
1822 || (cur->m_flags & MTEAM && !(ignored[cur->m_from] & MTEAM)))
1823 sendClientPacket((struct player_spacket *) & msg);
1824 else if (cur->m_flags & MINDIV)
1825 {
1826
1827 /* session stats now parsed here. parseQuery == true */
1828 /* means eat message 4/17/92 TC */
1829
1830 if (!parseQuery(&msg))
1831 if (ignored[cur->m_from] & MINDIV)
1832 bounce("That player is currently ignoring you.",
1833 cur->m_from);
1834 else
1835 sendClientPacket((struct player_spacket *) & msg);
1836 }
1837 }
1838 msgCurrent = (msgCurrent + 1) % MAXMESSAGE;
1839 }
1840 }
1841
1842 /* Asteroid/Nebulae socket code (5/16/95 rpg) */
1843
1844 #define DIM (MAX_GWIDTH/TGRID_GRANULARITY)
1845
1846 void
1847 updateTerrain()
1848 {
1849 int i;
1850 int j, maxfor;
1851 int status;
1852 int npkts;
1853 struct terrain_packet2 tpkt;
1854 struct terrain_info_packet2 tinfo_pkt;
1855 unsigned long olen = DIM * DIM, dlen = DIM * DIM / 1000 + DIM * DIM + 13;
1856 #if defined(T_DIAG) || defined(T_DIAG2)
1857 char buf[80];
1858 #endif
1859 unsigned char origBuf[DIM * DIM];
1860 unsigned char gzipBuf[DIM * DIM / 1000 +
1861 DIM * DIM + 13];
1862 /*
1863 * Don't ask me. The compression libs need (original size + 0.1% + 12
1864 * bytes).
1865 */
1866 /*
1867 * Note - this will have to be RADICALLY changed if alt1/alt2 are sent as
1868 * well.
1869 */
1870
1871 /* check to see if client can handle the terrain data first */
1872 if (F_terrain)
1873 {
1874 if (galaxyValid[me->p_no])
1875 return;
1876
1877 #if defined(T_DIAG) || defined(T_DIAG2)
1878 {
1879 char buf[80];
1880 sprintf(buf, "pno: %d gIsense: %d", me->p_no, galaxyValid[me->p_no]);
1881 pmessage(buf, 0, MALL, MSERVA);
1882 }
1883 #endif
1884 galaxyValid[me->p_no] = 1;
1885 /* Send initial packet. */
1886 tinfo_pkt.type = SP_TERRAIN_INFO2;
1887 tinfo_pkt.xdim = htons(DIM);
1888 tinfo_pkt.ydim = htons(DIM);
1889 sendClientPacket((struct player_spacket *) & tinfo_pkt);
1890 for (i = 0; i < DIM * DIM; i++)
1891 {
1892 origBuf[i] = terrain_grid[i].types; /* pack types field into
1893 * array */
1894 }
1895 #if defined(T_DIAG) || defined(T_DIAG2)
1896 status = compress(gzipBuf, &dlen, origBuf, olen);
1897 if (status != Z_OK)
1898 {
1899 pmessage("TERRAIN: Cannot gzip terrain grid.", 0, MALL, MSERVA);
1900 return;
1901 }
1902 else
1903 {
1904 sprintf(buf, "TERRAIN: Original length %d, compressed length %d", DIM * DIM, dlen);
1905 pmessage(buf, 0, MALL, MSERVA);
1906 }
1907 #else
1908 compress(gzipBuf, &dlen, origBuf, olen);
1909 #endif
1910 npkts = (dlen >> LOG2NTERRAIN);
1911 if (dlen & TERRAIN_MASK)
1912 {
1913 npkts++; /* require a partial packet */
1914 }
1915 for (i = 1; i <= npkts; i++)
1916 {
1917 tpkt.type = SP_TERRAIN2;
1918 tpkt.sequence = (unsigned char) i;
1919 tpkt.total_pkts = (unsigned char) npkts;
1920 if (i < npkts)
1921 {
1922 maxfor = tpkt.length = NTERRAIN;
1923 }
1924 else
1925 {
1926 maxfor = tpkt.length = (dlen & TERRAIN_MASK);
1927 }
1928 for (j = 0; j < maxfor; j++)
1929 {
1930 tpkt.terrain_type[j] = gzipBuf[((i - 1) << LOG2NTERRAIN) + j];
1931 }
1932 /* ok, packet is filled in, send it */
1933 #ifdef T_DIAG2
1934 sprintf(buf, "Sending terrain packet %d of %d", tpkt.sequence, tpkt.total_pkts);
1935 pmessage(buf, 0, MALL, MSERVA);
1936 #endif
1937 sendClientPacket((struct player_spacket *) & tpkt);
1938 }
1939 }
1940 #ifdef FEATURE_DIAG
1941 else
1942 {
1943 pmessage("Mis-timed terrain data (F_terrain = 0)!", 0, MALL, MSERVA);
1944 }
1945 #endif
1946 }
1947
1948 void
1949 updateMOTD()
1950 {
1951 static int spinner = 0;
1952
1953 if (--spinner < 0)
1954 {
1955 static struct stat oldstat;
1956 static int firsttime = 1;
1957
1958 char *path;
1959 struct stat newstat;
1960 struct obvious_packet pkt;
1961
1962 spinner = 10;
1963
1964 if (!firsttime)
1965 {
1966 path = build_path(MOTD);
1967 stat(path, &newstat);
1968 if (newstat.st_ino == oldstat.st_ino &&
1969 newstat.st_mtime == oldstat.st_mtime)
1970 return;
1971 oldstat.st_ino = newstat.st_ino;
1972 oldstat.st_mtime = newstat.st_mtime;
1973
1974 pkt.type = SP_NEW_MOTD;
1975 sendClientPacket((struct player_spacket *) & pkt);
1976 }
1977 else
1978 {
1979 sendMotd(); /* can't build_path before this */
1980 path = build_path(MOTD);
1981 stat(path, &oldstat);
1982 /* printf("%s: %d, %d\n", path, oldstat.st_ino, oldstat.st_mtime); */
1983 firsttime = 0;
1984 }
1985 }
1986 }
1987
1988 void
1989 sendQueuePacket(pos)
1990 short int pos;
1991 {
1992 struct queue_spacket qPacket;
1993
1994 qPacket.type = SP_QUEUE;
1995 qPacket.pos = htons(pos);
1996 sendClientPacket((struct player_spacket *) & qPacket);
1997 flushSockBuf();
1998 }
1999
2000 void
2001 sendClientPacket(packet)
2002 struct player_spacket *packet;
2003 {
2004 sendClientSizedPacket(packet, -1);
2005 }
2006
2007 void
2008 sendClientSizedPacket(packet, size)
2009 /* Pick a random type for the packet */
2010 struct player_spacket *packet;
2011 int size;
2012 {
2013 int orig_type;
2014 int issc;
2015 static int oldStatus = POUTFIT;
2016
2017 #if 0
2018 if (blk_metaserver)
2019 #endif
2020 #ifdef SHOW_PACKETS
2021 {
2022 FILE *logfile;
2023 char *paths;
2024 paths = build_path("logs/metaserver.log");
2025 logfile = fopen(paths, "a");
2026 if (logfile)
2027 {
2028 fprintf(logfile, "Sending packet type %d\n", (int) packet->type);
2029 fclose(logfile);
2030 }
2031
2032 }
2033 #endif
2034
2035 #ifdef T_DIAG2
2036 if ((packet->type == SP_TERRAIN2) || (packet->type == SP_TERRAIN_INFO2))
2037 {
2038 pmessage("Sending TERRAIN packet\n", 0, MALL, MSERVA);
2039 }
2040 #endif
2041
2042 orig_type = packet->type;
2043 #if 0
2044 packet->type &= ~(0x40 | 0x80); /* clear special flags */
2045 #else
2046 packet->type &= (char) 0x3f; /* above doesn't work? 4/18/92 TC */
2047 #endif
2048 #ifdef MAYBE
2049 /*
2050 * If we're dead, dying, or just born, we definitely want the transmission
2051 * to get through (otherwise we can get stuck). I don't think this will be
2052 * a problem for anybody, though it might hang for a bit if the TCP
2053 * connection is bad.
2054 */
2055 /* Okay, now I'm not so sure. Whatever. */
2056 if (oldStatus != PALIVE || (me != NULL && me->p_status != PALIVE))
2057 orig_type = packet->type | 0x80; /* pretend it's critical */
2058 #endif
2059
2060 /* if we're not given the size, calculate it */
2061 if (size < 0)
2062 {
2063 if (size_of_spacket(packet) == 0)
2064 {
2065 printf("Attempt to send strange packet %d\n", packet->type);
2066 return;
2067 }
2068 size = size_of_spacket(packet);
2069 }
2070 else
2071 {
2072 /* pad to 32-bits */
2073 size = ((size - 1) / 4 + 1) * 4;
2074 }
2075
2076 packetsSent[packet->type]++;
2077
2078
2079 if (commMode == COMM_TCP
2080 || (commMode == COMM_UDP && udpMode == MODE_TCP))
2081 {
2082 switch (orig_type)
2083 {
2084 case SP_MOTD:
2085 case SP_MOTD_PIC:
2086 /* these can afford to be delayed */
2087 sendTCPdeferred((void *) packet, size);
2088 break;
2089
2090 default:
2091 /* business as usual, TCP */
2092 sendTCPbuffered((void *) packet, size);
2093 break;
2094 }
2095 }
2096 else
2097 {
2098 /*
2099 * do UDP stuff unless it's a "critical" packet (note that both kinds get
2100 * a sequence number appended) (FIX)
2101 */
2102 issc = 0;
2103 switch (orig_type)
2104 {
2105 case SP_KILLS:
2106 case SP_TORP_INFO:
2107 case SP_THINGY_INFO:
2108 case SP_PHASER:
2109 case SP_PLASMA_INFO:
2110 case SP_YOU | 0x40: /* ??? what is this? */
2111 case SP_STATUS:
2112 case SP_STATUS2:
2113 case SP_PLANET:
2114 case SP_PLANET2:
2115 case SP_FLAGS:
2116 case SP_HOSTILE:
2117 /*
2118 * these are semi-critical; flag as semi-critical and fall through
2119 */
2120 issc = 1;
2121
2122 case SP_PLAYER:
2123 case SP_TORP:
2124 #ifdef SHORT_PACKETS
2125 case SP_S_TORP:
2126 case SP_S_8_TORP:
2127 #endif
2128 case SP_THINGY:
2129 case SP_YOU:
2130 case SP_PLASMA:
2131 case SP_STATS:
2132 case SP_STATS2:
2133 /* case SP_SCAN: */
2134 case SP_PING:
2135 case SP_UDP_REPLY: /* only reply when COMM_UDP is SWITCH_VERIFY */
2136 /* these are non-critical updates; send them via UDP */
2137 V_UDPDIAG(("Sending type %d\n", packet->type));
2138 packets_sent++;
2139 sendUDPbuffered(issc, (void *) packet, size);
2140 break;
2141
2142 case SP_MOTD:
2143 case SP_MOTD_PIC:
2144 sendTCPdeferred((void *) packet, size);
2145 break;
2146
2147 default:
2148 sendTCPbuffered((void *) packet, size);
2149 break;
2150 }
2151 }
2152
2153 if (me != NULL)
2154 oldStatus = me->p_status;
2155 }
2156
2157 /*
2158 * flushSockBuf, socketPause, socketWait were here
2159 */
2160
2161 /* Find out if client has any requests */
2162 int
2163 readFromClient()
2164 {
2165 struct timeval timeout;
2166 fd_set readfds, writefds;
2167 int retval = 0;
2168
2169 if (clientDead)
2170 return (0);
2171
2172 timeout.tv_sec = 0;
2173 timeout.tv_usec = 0;
2174
2175 build_select_masks(&readfds, &writefds);
2176
2177 if (select(32, &readfds, &writefds, (fd_set *) 0, &timeout) != 0)
2178 {
2179 /* Read info from the xtrek client */
2180 if (FD_ISSET(sock, &readfds))
2181 {
2182 retval += doRead(sock);
2183 }
2184 if (udpSock >= 0 && FD_ISSET(udpSock, &readfds))
2185 {
2186 V_UDPDIAG(("Activity on UDP socket\n"));
2187 retval += doRead(udpSock);
2188 }
2189 if (retval == 0 && /* no other traffic */
2190 FD_ISSET(sock, &writefds))
2191 {
2192 flushDeferred(); /* we have an eye in the packet hurricane */
2193 }
2194 }
2195 return (retval != 0); /* convert to 1/0 */
2196 }
2197
2198 static int
2199 input_allowed(packettype)
2200 int packettype;
2201 {
2202 switch (packettype)
2203 {
2204 case CP_MESSAGE:
2205 case CP_SOCKET:
2206 case CP_OPTIONS:
2207 case CP_BYE:
2208 case CP_UPDATES:
2209 case CP_RESETSTATS:
2210 case CP_RESERVED:
2211 case CP_RSA_KEY:
2212 case CP_ASK_MOTD:
2213 case CP_PING_RESPONSE:
2214 case CP_UDP_REQ:
2215 #ifdef FEATURE
2216 case CP_FEATURE:
2217 #endif
2218 #ifdef SHORT_PACKETS
2219 case CP_S_MESSAGE:
2220 #endif
2221 return 1;
2222 default:
2223 if (!me)
2224 return;
2225
2226 if (me->p_status == PTQUEUE)
2227 return (packettype == CP_OUTFIT
2228 );
2229 else if (me->p_status == POBSERVE)
2230 return (packettype == CP_QUIT
2231 || packettype == CP_PLANLOCK
2232 || packettype == CP_PLAYLOCK
2233 || packettype == CP_SCAN
2234 || packettype == CP_SEQUENCE /* whatever this is */
2235 );
2236
2237 if (inputMask >= 0 && inputMask != packettype)
2238 return 0;
2239 if (me == NULL)
2240 return 1;
2241 if (!(me->p_flags & (PFWAR | PFREFITTING)))
2242 return 1;
2243
2244 return 0;
2245 }
2246 }
2247
2248 static int rsock; /* ping stuff */
2249
2250 /* ripped out of above routine */
2251 int
2252 doRead(asock)
2253 int asock;
2254 {
2255 struct timeval timeout;
2256 /* int readfds; */
2257 fd_set readfds;
2258 char buf[BUFSIZ * 2];
2259 char *bufptr;
2260 int size;
2261 int count;
2262 int temp;
2263
2264 rsock = asock; /* need the socket in the ping handler
2265 * routine */
2266
2267 timeout.tv_sec = 0;
2268 timeout.tv_usec = 0;
2269 /* readfds = 1<<asock; */
2270 FD_ZERO(&readfds);
2271 FD_SET(asock, &readfds);
2272 /* Read info from the xtrek server */
2273 count = read(asock, buf, BUFSIZ * 2);
2274 if (count <= 0)
2275 {
2276 #if DEBUG
2277 /* (this happens when the client hits 'Q') */
2278 fprintf(stderr, "1) read() failed in doRead (%d, error %d)\n",
2279 count, errno);
2280 fprintf(stderr, "asock=%d, sock=%d\n", asock, sock);
2281 #endif
2282 if (asock == udpSock)
2283 {
2284 if (errno == ECONNREFUSED)
2285 {
2286 struct sockaddr_in addr;
2287
2288 UDPDIAG(("Hiccup(%d)! Reconnecting\n", errno));
2289 addr.sin_addr.s_addr = remoteaddr;
2290 addr.sin_port = htons(udpClientPort);
2291 addr.sin_family = AF_INET;
2292 if (connect(udpSock, (struct sockaddr *) & addr, sizeof(addr)) < 0)
2293 {
2294 perror("hiccup connect");
2295 UDPDIAG(("Unable to reconnect\n"));
2296 /* and fall through to disconnect */
2297 }
2298 else
2299 {
2300 UDPDIAG(("Reconnect successful\n"));
2301 return (0);
2302 }
2303 }
2304 UDPDIAG(("*** UDP disconnected (res=%d, err=%d)\n",
2305 count, errno));
2306 printUdpInfo();
2307 closeUdpConn();
2308 commMode = COMM_TCP;
2309 return (0);
2310 }
2311 clientDead = 1;
2312 return (0);
2313 }
2314 bufptr = buf;
2315 while (bufptr < buf + count)
2316 {
2317 if (*bufptr < 1 ||
2318 (unsigned char) *bufptr > NUM_PACKETS ||
2319 size_of_cpacket((void *) bufptr) == 0)
2320 {
2321 printf("Unknown packet type: %d, aborting...\n", *bufptr);
2322 return (0);
2323 }
2324 size = size_of_cpacket(bufptr);
2325 while (size > count + (buf - bufptr))
2326 {
2327 /*
2328 * We wait for up to twenty seconds for rest of packet. If we don't get
2329 * it, we assume the client died.
2330 */
2331 timeout.tv_sec = 20;
2332 timeout.tv_usec = 0;
2333 /* readfds=1<<asock; */
2334 FD_ZERO(&readfds);
2335 FD_SET(asock, &readfds);
2336 if (select(32, &readfds, 0, 0, &timeout) == 0)
2337 {
2338 logmessage("Died while waiting for packet...");
2339 fprintf(stderr, "1a) read() failed (%d, error %d)\n",
2340 count, errno);
2341 clientDead = 1;
2342 return (0);
2343 }
2344 temp = read(asock, buf + count, size - (count + (buf - bufptr)));
2345 if (temp <= 0)
2346 {
2347 if (errno != EINTR)
2348 {
2349 sprintf(buf, "Died in second read(), return=%d", temp);
2350 logmessage(buf);
2351 fprintf(stderr, "2) read() failed (%d, error %d)\n",
2352 count, errno);
2353 clientDead = 1;
2354 return (0);
2355 }
2356 }
2357 else
2358 count += temp;
2359 }
2360 /*
2361 * Check to see if the handler is there and the request is legal. The
2362 * code is a little ugly, but it isn't too bad to worry about yet.
2363 */
2364 #if 0
2365 {
2366 FILE *logfile;
2367 char *paths;
2368 if (blk_metaserver)
2369 {
2370 paths = build_path("logs/metaserver.log");
2371 logfile = fopen(paths, "a");
2372 if (logfile)
2373 {
2374 fprintf(logfile, "Receiving packet type %d\n", (int) *bufptr);
2375 fclose(logfile);
2376 }
2377 }
2378 }
2379 #endif
2380 packetsReceived[(unsigned char) *bufptr]++;
2381
2382 if (asock == udpSock)
2383 packets_received++;
2384
2385 if (handlers[(unsigned char) *bufptr].handler != NULL)
2386 {
2387 if (input_allowed(*bufptr))
2388 {
2389 if (me && me->p_flags & PFSELFDEST
2390 && *bufptr != CP_PING_RESPONSE)
2391 {
2392 me->p_flags &= ~PFSELFDEST;
2393 warning("Self Destruct has been canceled");
2394 }
2395 (*(handlers[(unsigned char) *bufptr].handler)) (bufptr);
2396 }
2397 /* Otherwise we ignore the request */
2398 }
2399 else
2400 {
2401 printf("Handler for packet %d not installed...\n", *bufptr);
2402 }
2403 bufptr += size;
2404 if (bufptr > buf + BUFSIZ)
2405 {
2406 memcpy(buf, buf + BUFSIZ, BUFSIZ);
2407 if (count == BUFSIZ * 2)
2408 {
2409 /* readfds = 1<<asock; */
2410 FD_ZERO(&readfds);
2411 FD_SET(asock, &readfds);
2412 if (select(32, &readfds, 0, 0, &timeout))
2413 {
2414 temp = read(asock, buf + BUFSIZ, BUFSIZ);
2415 count = BUFSIZ + temp;
2416 if (temp <= 0)
2417 {
2418 sprintf(buf, "Died in third read(), return=%d", temp);
2419 fprintf(stderr, "3) read() failed (%d, error %d)\n",
2420 count, errno);
2421 logmessage(buf);
2422 clientDead = 1;
2423 return (0);
2424 }
2425 }
2426 else
2427 {
2428 count = BUFSIZ;
2429 }
2430 }
2431 else
2432 {
2433 count -= BUFSIZ;
2434 }
2435 bufptr -= BUFSIZ;
2436 }
2437 }
2438 return (1);
2439 }
2440
2441 void
2442 handleTorpReq(packet)
2443 struct torp_cpacket *packet;
2444 {
2445 ntorp((CARD8) packet->dir, (int) TMOVE);
2446 }
2447
2448 void
2449 handlePhasReq(packet)
2450 struct phaser_cpacket *packet;
2451 {
2452 phaser(packet->dir);
2453 }
2454
2455 void
2456 handleSpeedReq(packet)
2457 struct speed_cpacket *packet;
2458 {
2459 set_speed(packet->speed, 1);
2460 }
2461
2462 void
2463 handleDirReq(packet)
2464 struct dir_cpacket *packet;
2465 {
2466 me->p_flags &= ~(PFPLOCK | PFPLLOCK);
2467 set_course(packet->dir);
2468 }
2469
2470 void
2471 handleShieldReq(packet)
2472 struct shield_cpacket *packet;
2473 {
2474 if (packet->state)
2475 {
2476 shield_up();
2477 }
2478 else
2479 {
2480 shield_down();
2481 }
2482 }
2483
2484 void
2485 handleRepairReq(packet)
2486 struct repair_cpacket *packet;
2487 {
2488 if (packet->state)
2489 {
2490 repair();
2491 }
2492 else
2493 {
2494 me->p_flags &= ~(PFREPAIR);
2495 }
2496 }
2497
2498 void
2499 handleOrbitReq(packet)
2500 struct orbit_cpacket *packet;
2501 {
2502 if (packet->state)
2503 {
2504 orbit();
2505 }
2506 else
2507 {
2508 me->p_flags &= ~PFORBIT;
2509 #if 0
2510 planets[me->p_planet].pl_torbit &= ~me->p_team;
2511 #endif
2512 if (me->p_flags & PFDOCK)
2513 {
2514 if (players[me->p_docked].p_speed > 4)
2515 {
2516 warning("It's unsafe to disengage from bases while over warp 4.");
2517 return;
2518 }
2519 else
2520 undock_player(me);
2521 }
2522 }
2523 }
2524
2525 /*-----------------------------PRACTICE_ROBOT-----------------------------*/
2526 /*
2527 * Send in a practice robot. You can only bring i a practice robot if no
2528 * other players are in the game.
2529 */
2530
2531 static void
2532 practice_robo()
2533 {
2534 char *paths; /* to hold dot dir path */
2535 char *arg1;
2536 register int i; /* looping var */
2537 register struct player *j; /* to point to players */
2538 static struct timeval space = {0, 0};
2539
2540 if (!temporally_spaced(&space, 1000000)) /* damn auto-repeating... */
2541 return;
2542
2543 for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
2544 {
2545 if (j->p_status != PALIVE) /* if payer not alive, that's ok */
2546 continue;
2547 if (j == me) /* ignore myself */
2548 continue;
2549 warning("Can't send in practice robot with other players in the game.");
2550 return; /* another player discovered--out of here */
2551 }
2552
2553 if (fork() == 0)
2554 { /* do if fork successful */
2555 (void) r_signal(SIGALRM, SIG_DFL);
2556 (void) close(0);
2557 (void) close(1);
2558 (void) close(2);
2559 switch (me->p_team)
2560 { /* decide which teaem robot is on */
2561 case FED:
2562 arg1 = "-Tf"; /* fed option */
2563 break;
2564 case ROM:
2565 arg1 = "-Tr"; /* rom option */
2566 break;
2567 case KLI:
2568 arg1 = "-Tk"; /* klingon option */
2569 break;
2570 case ORI:
2571 arg1 = "-To"; /* orion option */
2572 break;
2573 default:
2574 arg1 = "-Ti"; /* in case something screwy happens */
2575 break;
2576 }
2577
2578 paths = build_path(ROBOT);
2579
2580 execl(paths, "robot", arg1, "-p", "-f", "-h", 0);
2581 _exit(1); /* failure :( died at birth */
2582 }
2583 }
2584
2585 /*--------------------------------------------------------------------------*/
2586
2587 /* ARGSUSED */
2588 void
2589 handlePractrReq(packet)
2590 struct practr_cpacket *packet;
2591 {
2592 practice_robo();
2593 }
2594
2595 void
2596 handleBombReq(packet)
2597 struct bomb_cpacket *packet;
2598 {
2599 if (packet->state)
2600 {
2601 bomb_planet();
2602 }
2603 else
2604 {
2605 me->p_flags &= ~(PFBOMB);
2606 }
2607 }
2608
2609 void
2610 handleBeamReq(packet)
2611 struct beam_cpacket *packet;
2612 {
2613 if (packet->state == 1)
2614 {
2615 beam_up();
2616 }
2617 else if (packet->state)
2618 {
2619 beam_down();
2620 }
2621 else
2622 {
2623 me->p_flags &= ~(PFBEAMUP | PFBEAMDOWN);
2624 }
2625 }
2626
2627 void
2628 handleCloakReq(packet)
2629 struct cloak_cpacket *packet;
2630 {
2631 if (packet->state)
2632 {
2633 cloak_on();
2634 }
2635 else
2636 {
2637 cloak_off();
2638 }
2639 }
2640
2641 /* ARGSUSED */
2642 void
2643 handleDetTReq(packet)
2644 struct det_torps_cpacket *packet;
2645 {
2646 detothers();
2647 }
2648
2649 /* ARGSUSED */
2650 void
2651 handleCopilotReq(packet)
2652 struct copilot_cpacket *packet;
2653 {
2654 /*
2655 * Unsupported... if (packet->state) { me->p_flags |= PFCOPILOT; } else {
2656 * me->p_flags &= ~PFCOPILOT; }
2657 */
2658 }
2659
2660 void
2661 handleOutfit(packet)
2662 struct outfit_cpacket *packet;
2663 {
2664 shipPick = packet->ship;
2665 teamPick = packet->team;
2666 }
2667
2668 void
2669 sendPickokPacket(state)
2670 int state;
2671 {
2672 struct pickok_spacket pickPack;
2673
2674 pickPack.type = SP_PICKOK;
2675 pickPack.state = state;
2676 sendClientPacket((struct player_spacket *) & pickPack);
2677 }
2678
2679 void
2680 handleLoginReq(packet)
2681 struct login_cpacket *packet;
2682 {
2683 if (packet->pad2 == 0x69)
2684 {
2685 if (packet->pad3 == 0x42)
2686 blk_flag = 1; /* added 1/19/93 KAO */
2687 if (packet->pad3 == 0x43)
2688 blk_flag = 2;
2689 }
2690 strncpy(namePick, packet->name, 16);
2691 namePick[15] = 0;
2692 strncpy(passPick, packet->password, 16);
2693 passPick[15] = 0;
2694 /* Is this a name query or a login? */
2695 if (packet->query)
2696 {
2697 passPick[15] = 1;
2698 }
2699 strncpy(login, packet->login, 16);
2700 login[15] = 0;
2701 }
2702
2703 void
2704 sendClientLogin(stats)
2705 struct stats *stats;
2706 {
2707 struct login_spacket logPacket;
2708 logPacket.pad2 = 69;
2709 if (configvals->galaxygenerator == 4)
2710 logPacket.pad3 = 88;
2711 else
2712 logPacket.pad3 = 42;
2713 logPacket.type = SP_LOGIN;
2714 if (stats == NULL)
2715 {
2716 logPacket.accept = 0;
2717 }
2718 else
2719 {
2720 logPacket.accept = 1;
2721 logPacket.flags = htonl(stats->st_flags);
2722 }
2723 sendClientPacket((struct player_spacket *) & logPacket);
2724 }
2725
2726 void
2727 handlePlasmaReq(packet)
2728 struct plasma_cpacket *packet;
2729 {
2730 if (me->p_specweap & SFNHASMISSILE)
2731 {
2732 fire_missile_dir(packet->dir);
2733 }
2734 else if (me->p_specweap & SFNPLASMAARMED)
2735 {
2736 nplasmatorp(packet->dir, PTMOVE);
2737 }
2738 else
2739 {
2740 warning("This ship is armed with no special weapons");
2741 }
2742 }
2743
2744 void
2745 handleWarReq(packet)
2746 struct war_cpacket *packet;
2747 {
2748 declare_war(packet->newmask);
2749 }
2750
2751 void
2752 handlePlanlockReq(packet)
2753 struct planlock_cpacket *packet;
2754 {
2755 lock_planet(packet->pnum);
2756 }
2757
2758 void
2759 handlePlaylockReq(packet)
2760 struct playlock_cpacket *packet;
2761 {
2762 lock_player(packet->pnum);
2763 }
2764
2765 void
2766 handleDetMReq(packet)
2767 struct det_mytorp_cpacket *packet;
2768 {
2769 struct torp *atorp;
2770 short t;
2771
2772 /* you can det individual torps */
2773 t = ntohs(packet->tnum);
2774 if (t < 0)
2775 {
2776 struct missile *dr;
2777 int i, any;
2778
2779 any = 0;
2780
2781 for (i = 0; i < MAXTORP; i++)
2782 {
2783 atorp = &torps[me->p_no * MAXTORP + i];
2784 if (atorp->t_status == TMOVE || atorp->t_status == TSTRAIGHT)
2785 {
2786 atorp->t_status = TOFF;
2787 any = 1;
2788 }
2789 }
2790
2791 if (any)
2792 return;
2793
2794 for (i = 0; i < NPTHINGIES; i++)
2795 {
2796 dr = &missiles[me->p_no * NPTHINGIES + i];
2797 if (dr->ms_status == TMOVE || dr->ms_status == TSTRAIGHT)
2798 {
2799 switch (dr->ms_type)
2800 {
2801 case MISSILETHINGY:
2802 dr->ms_status = TOFF;
2803 break;
2804 case FIGHTERTHINGY:
2805 dr->ms_status = TRETURN;
2806 break;
2807 }
2808 any = 1;
2809 }
2810 }
2811
2812 /* any ? */
2813 }
2814 else
2815 {
2816
2817 if (t < 0 || t >= MAXPLAYER * MAXTORP)
2818 return;
2819 atorp = &torps[t];
2820
2821 if (atorp->t_owner != me->p_no)
2822 return;
2823 if (atorp->t_status == TMOVE || atorp->t_status == TSTRAIGHT)
2824 {
2825 atorp->t_status = TOFF;
2826 }
2827 }
2828 }
2829
2830 void
2831 handleTractorReq(packet)
2832 struct tractor_cpacket *packet;
2833 {
2834 int target;
2835 struct player *player;
2836
2837 if (weaponsallowed[WP_TRACTOR] == 0)
2838 {
2839 warning("Tractor beams haven't been invented yet.");
2840 return;
2841 }
2842 target = packet->pnum;
2843 if (packet->state == 0)
2844 {
2845 me->p_flags &= ~(PFTRACT | PFPRESS);
2846 return;
2847 }
2848 if (me->p_flags & PFCLOAK)
2849 {
2850 warning("Weapons's Officer: Cannot tractor while cloaked, sir!");
2851 return;
2852 }
2853 if (target < 0 || target >= MAXPLAYER || target == me->p_no)
2854 return;
2855 player = &players[target];
2856 if (player->p_flags & PFCLOAK)
2857 return;
2858 if (me->p_flags & PFDOCK && players[me->p_docked].p_speed > 4)
2859 {
2860 warning("It's unsafe to tractor while docked and moving at a warp greater then 4.");
2861 return;
2862 }
2863 if (ihypot(me->p_x - player->p_x, me->p_y - player->p_y) <
2864 (TRACTDIST) * me->p_ship.s_tractrng)
2865 {
2866 undock_player(me);
2867 me->p_flags &= ~PFORBIT;
2868 #if 0
2869 undock_player(player); /* harmless if they're not docked */
2870
2871 #if 0
2872 if (player->p_flags & PFORBIT)
2873 planets[player->p_planet].pl_torbit &= ~player->p_team;
2874 if (me->p_flags & PFORBIT)
2875 planets[me->p_planet].pl_torbit &= ~me->p_team;
2876 #endif
2877 player->p_flags &= ~(PFORBIT | PFDOCK);
2878 me->p_flags &= ~(PFORBIT | PFDOCK);
2879 #endif
2880 me->p_tractor = target;
2881 me->p_flags |= PFTRACT;
2882
2883 }
2884 else
2885 {
2886 warning("Weapon's Officer: Vessel is out of range of our tractor beam.");
2887 }
2888 }
2889
2890 void
2891 handleRepressReq(packet)
2892 struct repress_cpacket *packet;
2893 {
2894 int target;
2895 struct player *player;
2896
2897 if (weaponsallowed[WP_TRACTOR] == 0)
2898 {
2899 warning("Pressor beams haven't been invented yet.");
2900 return;
2901 }
2902 target = packet->pnum;
2903 if (packet->state == 0)
2904 {
2905 me->p_flags &= ~(PFTRACT | PFPRESS);
2906 return;
2907 }
2908 if (me->p_flags & PFCLOAK)
2909 {
2910 warning("Weapons's Officer: Cannot pressor while cloaked, sir!");
2911 return;
2912 }
2913 if (target < 0 || target >= MAXPLAYER || target == me->p_no)
2914 return;
2915 player = &players[target];
2916 if (player->p_flags & PFCLOAK)
2917 return;
2918 if (me->p_flags & PFDOCK && players[me->p_docked].p_speed > 4)
2919 {
2920 warning("It's unsafe to pressor while docked and moving at a warp greater then 4.");
2921 return;
2922 }
2923 if (ihypot(me->p_x - player->p_x, me->p_y - player->p_y) <
2924 (TRACTDIST) * me->p_ship.s_tractrng)
2925 {
2926 undock_player(me);
2927 me->p_flags &= ~PFORBIT;
2928 #if 0
2929 undock_player(player);
2930
2931 #if 0
2932 if (player->p_flags & PFORBIT)
2933 planets[player->p_planet].pl_torbit &= ~player->p_team;
2934 if (me->p_flags & PFORBIT)
2935 planets[me->p_planet].pl_torbit &= ~me->p_team;
2936 #endif
2937 player->p_flags &= ~(PFORBIT | PFDOCK);
2938 me->p_flags &= ~(PFORBIT | PFDOCK);
2939 #endif
2940 me->p_tractor = target;
2941 me->p_flags |= (PFTRACT | PFPRESS);
2942 }
2943 else
2944 {
2945 warning("Weapon's Officer: Vessel is out of range of our pressor beam.");
2946 }
2947 }
2948
2949 void
2950 sendMotdLine(line)
2951 char *line;
2952 {
2953 struct motd_spacket motdPacket;
2954
2955 motdPacket.type = SP_MOTD;
2956 strncpy(motdPacket.line, line, 80);
2957 motdPacket.line[79] = '\0';
2958 sendClientPacket((struct player_spacket *) & motdPacket);
2959 }
2960
2961 /* ARGSUSED */
2962 void
2963 handleCoupReq(packet)
2964 struct coup_cpacket *packet;
2965 {
2966 switch_special_weapon();
2967 }
2968
2969 void
2970 handleRefitReq(packet)
2971 struct refit_cpacket *packet;
2972 {
2973 do_refit(packet->ship);
2974 }
2975
2976 void
2977 handleMessageReq(packet)
2978 struct mesg_cpacket *packet;
2979 {
2980 char addrbuf[9];
2981 static long lasttime = 0 /* , time() */ ;
2982 static int balance = 0; /* make sure he doesn't get carried away */
2983 long thistime;
2984
2985 int isCensured(); /* "shut up and play" code 7/21/91 TC */
2986 int parseIgnore(); /* still more code, 7/24/91 TC */
2987
2988 /*
2989 * Some random code to make sure the player doesn't get carried away about
2990 * the number of messages he sends. After all, he could try to jam peoples
2991 * communications if we let him.
2992 */
2993
2994 thistime = time(NULL);
2995 if (lasttime != 0)
2996 {
2997 balance = balance - (thistime - lasttime);
2998 if (balance < 0)
2999 balance = 0;
3000 }
3001 lasttime = thistime;
3002 if (balance >= 15)
3003 {
3004 warning("Be quiet");
3005 balance += 3;
3006 if (balance > time(NULL) + 60)
3007 {
3008 balance = time(NULL) + 60;
3009 }
3010 return;
3011 }
3012 balance += 3;
3013 /* packet->mesg[69] = '\0'; */
3014 sprintf(addrbuf, " %s->", twoletters(me));
3015 if (parseIgnore(packet))
3016 return; /* moved this up 4/6/92 TC */
3017 if (packet->group & MGOD)
3018 {
3019 strcpy(addrbuf + 5, "GOD");
3020 }
3021 else if (packet->group & MALL)
3022 {
3023 sprintf(addrbuf + 5, "ALL");
3024 if (isCensured(me->p_login))
3025 {
3026 warning("You are censured. Message was not sent.");
3027 return;
3028 }
3029 }
3030 else if (packet->group & MTEAM)
3031 {
3032 if (packet->indiv != FED && packet->indiv != ROM &&
3033 packet->indiv != KLI && packet->indiv != ORI)
3034 return;
3035 if (isCensured(me->p_login) && (packet->indiv != me->p_team))
3036 {
3037 warning("You are censured. Message was not sent.");
3038 return;
3039 }
3040 sprintf(addrbuf + 5, teams[packet->indiv].shortname);
3041 }
3042 else if (packet->group & MINDIV)
3043 {
3044 if (packet->indiv < 0 || packet->indiv >= MAXPLAYER)
3045 return;
3046 if (players[packet->indiv].p_status == PFREE)
3047 return;
3048 if (isCensured(me->p_login) && (players[packet->indiv].p_team != me->p_team))
3049 {
3050 warning("You are censured. Message was not sent.");
3051 return;
3052 }
3053 if (ignored[packet->indiv] & MINDIV)
3054 {
3055 warning("You are ignoring that player. Message was not sent.");
3056 return;
3057 }
3058 if ((me->p_team != players[packet->indiv].p_team) &&
3059 (isCensured(players[packet->indiv].p_login)))
3060 {
3061 warning("That player is censured. Message was not sent.");
3062 return;
3063 }
3064 sprintf(addrbuf + 5, "%s ", twoletters(&players[packet->indiv]));
3065 }
3066 else
3067 {
3068 return;
3069 }
3070 #if 0
3071 if ((packet->group == MGOD
3072 || me->p_no == packet->indiv && packet->group == MINDIV)
3073 && parse_command_mess(packet->mesg, me->p_no))
3074 {
3075 /* message parsed. Eat it */
3076 }
3077 else
3078 {
3079 pmessage2(packet->mesg, packet->indiv, packet->group, addrbuf, me->p_no);
3080 }
3081 #else
3082 /* don't eat the parsed messages */
3083 pmessage2(packet->mesg, packet->indiv, packet->group, addrbuf, me->p_no);
3084 if (me->p_no == packet->indiv && packet->group == MINDIV)
3085 {
3086 char tmpbuf[sizeof(packet->mesg) + 1];
3087 strncpy(tmpbuf, packet->mesg, sizeof(packet->mesg));
3088 tmpbuf[sizeof(packet->mesg)] = 0;
3089 parse_command_mess(tmpbuf, me->p_no);
3090 }
3091 #endif
3092
3093 /*
3094 * Blech !!!
3095 *
3096 * Don't do this:
3097 *
3098 * if (me->p_no == packet->indiv && packet->mesg[0] == '_') me = &players[0];
3099 */
3100 }
3101
3102 /* ARGSUSED */
3103 void
3104 handleQuitReq(packet)
3105 struct quit_cpacket *packet;
3106 {
3107 if (me->p_status == POBSERVE)
3108 {
3109 me->p_status = PTQUEUE;
3110 return;
3111 }
3112 me->p_flags |= PFSELFDEST;
3113
3114 switch (me->p_ship.s_type)
3115 {
3116 case STARBASE:
3117 case WARBASE:
3118 selfdest = 60;
3119 break;
3120 default:
3121 selfdest = 10;
3122 }
3123
3124 selfdest = me->p_updates + selfdest * 10;
3125
3126 warning("Self destruct initiated");
3127 }
3128
3129 void
3130 sendMaskPacket(mask)
3131 int mask;
3132 {
3133 struct mask_spacket maskPacket;
3134
3135 maskPacket.type = SP_MASK;
3136 maskPacket.mask = mask;
3137 sendClientPacket((struct player_spacket *) & maskPacket);
3138 }
3139
3140 void
3141 handleOptionsPacket(packet)
3142 struct options_cpacket *packet;
3143 {
3144 mystats->st_flags = ntohl(packet->flags) |
3145 (mystats->st_flags & ST_CYBORG); /* hacked fix 8/24/91 TC */
3146 keeppeace = (mystats->st_flags / ST_KEEPPEACE) & 1;
3147 }
3148
3149 void
3150 handleSocketReq(packet)
3151 struct socket_cpacket *packet;
3152 {
3153 nextSocket = ntohl(packet->socket);
3154 userVersion = packet->version;
3155 userUdpVersion = packet->udp_version;
3156 }
3157
3158 /* ARGSUSED */
3159 void
3160 handleByeReq(packet)
3161 struct bye_cpacket *packet;
3162 {
3163 noressurect = 1;
3164 }
3165
3166 int
3167 checkVersion()
3168 {
3169 struct badversion_spacket packet;
3170
3171 if (userVersion != SOCKVERSION)
3172 {
3173 packet.type = SP_BADVERSION;
3174 packet.why = 0;
3175 sendClientPacket((struct player_spacket *) & packet);
3176 flushSockBuf();
3177 return (0);
3178 }
3179 return (1);
3180 }
3181
3182 void
3183 logEntry()
3184 {
3185 FILE *logfile;
3186 int curtime;
3187 char *paths;
3188
3189 paths = build_path(LOGFILENAME);
3190 logfile = fopen(paths, "a");
3191 if (!logfile)
3192 return;
3193 curtime = time(NULL);
3194
3195 #ifdef LOG_LONG_INFO /*-[ prints out long info to the log files ]-*/
3196
3197 fprintf(logfile, "Joining: %s, (%c) <%s@%s> %s", me->p_name,
3198 shipnos[me->p_no],
3199 me->p_login, /* debug 2/21/92 TMC */
3200
3201 #else
3202
3203 fprintf(logfile, "Joining: %s <%s@%s> %s", me->p_name, me->p_login,
3204
3205 #endif /*-[ LOG_LONG_INFO ]-*/
3206
3207 me->p_full_hostname,
3208 ctime((time_t *) & curtime));
3209
3210 fclose(logfile);
3211 }
3212
3213 /* gwrite was here */
3214
3215 void
3216 handleDockingReq(packet)
3217 struct dockperm_cpacket *packet;
3218 {
3219 int i;
3220
3221 if (allows_docking(me->p_ship))
3222 {
3223 if (me->p_speed > 4 && me->p_docked)
3224 {
3225 warning("It's unsafe to disengage other ships while over warp 4.");
3226 return;
3227 }
3228 else
3229 {
3230 for (i = 0; i < me->p_ship.s_numports; i++)
3231 base_undock(me, i);
3232 me->p_docked = 0;
3233
3234 if (packet->state)
3235 me->p_flags |= PFDOCKOK;
3236 else
3237 me->p_flags &= ~PFDOCKOK;
3238 }
3239 }
3240 }
3241
3242 void
3243 handleReset(packet)
3244 struct resetstats_cpacket *packet;
3245 {
3246 extern int startTkills, startTlosses, startTarms, startTplanets, startTticks;
3247
3248 if (packet->verify != 'Y')
3249 return;
3250
3251 /* Gee, they seem to want to reset their stats! Here goes... */
3252 #if 0
3253 mystats->st_maxkills = 0.0;
3254 mystats->st_kills = 0;
3255 mystats->st_losses = 0;
3256 mystats->st_armsbomb = 0;
3257 mystats->st_planets = 0;
3258 mystats->st_ticks = 0;
3259 mystats->st_tkills = 0;
3260 mystats->st_tlosses = 0;
3261 mystats->st_tarmsbomb = 0;
3262 mystats->st_tplanets = 0;
3263 mystats->st_tticks = 1;
3264 mystats->st_rank = 0;
3265 mystats->st_sbkills = 0;
3266 mystats->st_sblosses = 0;
3267 mystats->st_sbticks = 0;
3268 mystats->st_sbmaxkills = 0.0;
3269
3270 startTkills = mystats->st_tkills;
3271 startTlosses = mystats->st_tlosses;
3272 startTarms = mystats->st_tarmsbomb;
3273 startTplanets = mystats->st_tplanets;
3274 startTticks = mystats->st_tticks;
3275 #endif
3276
3277 mystats->st_genocides = 0;
3278 mystats->st_tmaxkills = 0.0;
3279 mystats->st_di = 0.0;
3280 mystats->st_tkills = 0;
3281 mystats->st_tlosses = 0;
3282 mystats->st_tarmsbomb = 0;
3283 mystats->st_tresbomb = 0;
3284 mystats->st_tdooshes = 0;
3285 mystats->st_tplanets = 0;
3286 mystats->st_tticks = 1;
3287 mystats->st_sbkills = 0;
3288 mystats->st_sblosses = 0;
3289 mystats->st_sbmaxkills = 0.0;
3290 mystats->st_sbticks = 1;
3291 mystats->st_wbkills = 0;
3292 mystats->st_wblosses = 0;
3293 mystats->st_wbmaxkills = 0.0;
3294 mystats->st_wbticks = 1;
3295 mystats->st_jsplanets = 0;
3296 mystats->st_jsticks = 1;
3297 mystats->st_rank = 0;
3298 mystats->st_royal = 0;
3299
3300 startTkills = mystats->st_tkills;
3301 startTlosses = mystats->st_tlosses;
3302 startTarms = mystats->st_tarmsbomb;
3303 startTplanets = mystats->st_tplanets;
3304 startTticks = mystats->st_tticks;
3305 }
3306
3307 void
3308 handleUpdatesReq(packet)
3309 struct updates_cpacket *packet;
3310 {
3311 struct itimerval udt;
3312 extern int interrupting; /* main.c */
3313 int min_delay = me->p_observer
3314 ? configvals->min_observer_upd_delay
3315 : configvals->min_upd_delay;
3316
3317 timerDelay = ntohl(packet->usecs);
3318 if (timerDelay < min_delay)
3319 timerDelay = min_delay;
3320 if (timerDelay >= 1000000)
3321 timerDelay = 999999;
3322
3323 if (interrupting)
3324 { /* only setitimer if the ntserv is configured
3325 * to handle it. It's NOT configured to
3326 * handle it in the outfit loop... */
3327 udt.it_interval.tv_sec = 0;
3328 udt.it_interval.tv_usec = timerDelay;
3329 udt.it_value.tv_sec = 0;
3330 udt.it_value.tv_usec = timerDelay;
3331 setitimer(ITIMER_REAL, &udt, 0);
3332 }
3333
3334 }
3335
3336 void
3337 logmessage(string)
3338 char *string;
3339 {
3340 FILE *fp;
3341 char *paths;
3342
3343 paths = build_path(LOGFILENAME);
3344
3345 fp = fopen(paths, "a");
3346 if (fp)
3347 {
3348 fprintf(fp, "%s\n", string);
3349 fclose(fp);
3350 }
3351 }
3352
3353 #if 0
3354 handleReserved(packet)
3355 struct reserved_cpacket *packet;
3356 {
3357 /* char temp[20]; */
3358 struct reserved_cpacket mycp;
3359 struct reserved_spacket mysp;
3360 char serverName[64]; /* now get serverName from system 8/2/92 TC */
3361
3362 if (testtime == 1)
3363 return;
3364 if (memcmp(packet->data, testdata, 16) != 0)
3365 {
3366 testtime = 1;
3367 return;
3368 }
3369 memcpy(mysp.data, testdata, 16);
3370 if (gethostname(serverName, 64))
3371 fprintf(stderr, "gethostname() error\n"); /* 8/2/92 TC */
3372 encryptReservedPacket(&mysp, &mycp, serverName, me->p_no);
3373 if (memcmp(packet->resp, mycp.resp, 16) != 0)
3374 {
3375 fprintf(stderr, "User verified incorrectly.\n");
3376 testtime = 1;
3377 return;
3378 }
3379 testtime = 0;
3380 }
3381
3382 #ifdef ATM_STUFF
3383 void
3384 dummy_()
3385 {
3386 if ((configvals->binconfirm == 2) &&
3387 !strcmp(packet->resp, "Cyborg"))
3388 {
3389 testtime = 0; /* accept */
3390 cyborg = 1;
3391 if (me->p_name[0] != '+')
3392 {
3393 temp[0] = '+'; /* indicate cyborg */
3394 strcpy(temp + 1, me->p_name); /* this happens AFTER entry, */
3395 temp[15] = '\0'; /* so changing enter() isn't */
3396 strcpy(me->p_name, temp); /* sufficient */
3397 }
3398 return;
3399 }
3400
3401 if (memcmp(packet->resp, mycp.resp, 16) != 0)
3402 {
3403 fprintf(stderr, "User verified incorrectly.\n");
3404 testtime = 1;
3405 return;
3406 }
3407
3408 testtime = 0;
3409 }
3410
3411 #endif
3412 #else
3413
3414 void
3415 handleRSAKey(packet)
3416 struct rsa_key_cpacket *packet;
3417 {
3418 #ifdef AUTHORIZE
3419 struct rsa_key_spacket mysp;
3420 char serverName[64];
3421
3422 if (testtime == 1)
3423 return;
3424 if (RSA_Client != 1)
3425 return;
3426 memcpy(mysp.data, testdata, KEY_SIZE);
3427 if (gethostname(serverName, 64))
3428 fprintf(stderr, "gethostname() error\n");
3429 if (decryptRSAPacket(&mysp, packet, serverName))
3430 {
3431 fprintf(stderr, "User verified incorrectly.\n");
3432 testtime = 1;
3433 return;
3434 }
3435 testtime = 0;
3436 #endif /* AUTHORIZE */
3437 }
3438
3439 void
3440 handleReserved(packet)
3441 struct reserved_cpacket *packet;
3442 {
3443 #ifdef AUTHORIZE
3444 struct reserved_cpacket mycp;
3445 struct reserved_spacket mysp;
3446 struct rsa_key_spacket rsp;
3447 char serverName[64]; /* now get serverName from system 8/2/92 TC */
3448
3449 if (testtime == 1)
3450 return;
3451 if (memcmp(packet->data, testdata, RESERVED_SIZE) != 0)
3452 {
3453 testtime = 1;
3454 return;
3455 }
3456 if (!strncmp(packet->resp, RSA_VERSION, 3))
3457 {
3458 /* This is an RSA type client */
3459 RSA_Client = 2;
3460 warning(RSA_VERSION);
3461 if (!strncmp(packet->resp, RSA_VERSION, strlen("RSA v??")))
3462 {
3463 /* This is the right major version */
3464 RSA_Client = 1;
3465 makeRSAPacket(&rsp);
3466 memcpy(testdata, rsp.data, KEY_SIZE);
3467 sendClientPacket((struct player_spacket *) & rsp);
3468 return;
3469 }
3470 testtime = 1;
3471 return;
3472 }
3473 memcpy(mysp.data, testdata, RESERVED_SIZE);
3474 if (gethostname(serverName, 64))
3475 fprintf(stderr, "gethostname() error\n"); /* 8/2/92 TC */
3476 encryptReservedPacket(&mysp, &mycp, serverName, me->p_no);
3477 if (memcmp(packet->resp, mycp.resp, RESERVED_SIZE) != 0)
3478 {
3479 fprintf(stderr, "User verified incorrectly.\n");
3480 testtime = 1;
3481 return;
3482 }
3483 /* Use .sysdef CONFIRM flag to allow old style clients. */
3484 if (configvals->binconfirm == 2)
3485 testtime = 0;
3486 else
3487 testtime = 1;
3488
3489 #endif /* AUTHORIZE */
3490 }
3491
3492 #endif
3493
3494 void
3495 handleScan(packet) /* ATM */
3496 struct scan_cpacket *packet;
3497 {
3498 #if 0
3499 struct scan_spacket response;
3500 struct player *pp;
3501
3502 memset(&response, 0, sizeof(struct scan_spacket));
3503 response.type = SP_SCAN;
3504 response.pnum = packet->pnum;
3505 if (!weaponsallowed[WP_SCANNER])
3506 {
3507 warning("Scanners haven't been invented yet");
3508 response.success = 0;
3509 }
3510 else
3511 {
3512 response.success = scan(packet->pnum);
3513
3514 if (response.success)
3515 {
3516 /fill in all the goodies /
3517 pp = &players[packet->pnum];
3518 response.p_fuel = htonl(pp->p_fuel);
3519 response.p_armies = htonl(pp->p_armies);
3520 response.p_shield = htonl(pp->p_shield);
3521 response.p_damage = htonl(pp->p_damage);
3522 response.p_etemp = htonl(pp->p_etemp);
3523 response.p_wtemp = htonl(pp->p_wtemp);
3524 }
3525 }
3526 sendClientPacket((struct player_spacket *) & response);
3527 #endif
3528 }
3529
3530
3531 void
3532 handlePingResponse(packet)
3533 struct ping_cpacket *packet;
3534 {
3535 char buf[80];
3536 /* client requests pings by sending pingme == 1 on TCP socket */
3537
3538 if (rsock == sock)
3539 {
3540 if (!ping && packet->pingme == 1)
3541 {
3542 ping = 1;
3543 sprintf(buf, "Server sending ping packets at %d second intervals",
3544 configvals->ping_period);
3545 warning(buf);
3546 return;
3547 }
3548 /* client says stop */
3549 else if (ping && !packet->pingme)
3550 {
3551 ping = 0;
3552 warning("Server no longer sending ping packets.");
3553 return;
3554 }
3555 }
3556 pingResponse(packet); /* ping.c */
3557 }
3558
3559 #ifdef SHORT_PACKETS
3560
3561 void
3562 handleShortReq(packet)
3563 struct shortreq_cpacket *packet;
3564 {
3565 struct shortreply_spacket resp;
3566
3567 switch (packet->req)
3568 {
3569 case SPK_VOFF:
3570 send_short = 0;
3571 warning("Not sending variable and short packets. Back to default.");
3572 if (udpSock >= 0 && udpMode == MODE_FAT)
3573 forceUpdate();
3574 break;
3575
3576 case SPK_VON:
3577 if (packet->version != (char) SHORTVERSION)
3578 {
3579 warning("Your SHORT Protocol Version is not right!");
3580 packet->req = SPK_VOFF;
3581 break;
3582 }
3583 if (!send_short)
3584 warning("Sending variable and short packets. "); /* send only firsttime */
3585 send_short = 1;
3586 resp.winside = ntohs(WINSIDE);
3587 resp.gwidth = ntohl(GWIDTH);
3588 break;
3589
3590 case SPK_MOFF:
3591 send_mesg = 1;
3592 warning("Obsolete!");
3593 packet->req = SPK_MON;
3594 break;
3595
3596 case SPK_MON:
3597 send_mesg = 1;
3598 warning("All messages sent.");
3599 break;
3600
3601 case SPK_M_KILLS:
3602 send_kmesg = 1;
3603 warning("Kill messages sent");
3604 break;
3605
3606 case SPK_M_NOKILLS:
3607 send_kmesg = 1;
3608 warning("Obsolete!");
3609 packet->req = SPK_M_KILLS;
3610 break;
3611
3612 case SPK_M_WARN:
3613 send_warn = 1;
3614 warning("Warn messages sent");
3615 break;
3616
3617 case SPK_M_NOWARN:
3618 send_warn = 1;
3619 warning("Obsolete!");
3620 packet->req = SPK_M_WARN;
3621 break;
3622
3623 case SPK_SALL:
3624 if (send_short)
3625 {
3626 spk_update_sall = 1;
3627 spk_update_all = 0;
3628 forceUpdate();
3629 }
3630 else
3631 warning("Activate SHORT Packets first!");
3632 return;
3633
3634 case SPK_ALL:
3635 if (send_short)
3636 {
3637 spk_update_sall = 0;
3638 spk_update_all = 1;
3639 forceUpdate();
3640 }
3641 else
3642 warning("Activate SHORT Packets first!");
3643 return;
3644
3645 default:
3646 warning("Unknown short packet code");
3647 return;
3648 }
3649
3650 resp.type = SP_S_REPLY;
3651 resp.repl = (char) packet->req;
3652
3653 sendClientPacket((struct player_spacket *) & resp);
3654 }
3655
3656 void
3657 handleThresh(packet)
3658 struct threshold_cpacket *packet;
3659 {
3660 send_threshold = packet->thresh;
3661 #ifdef SHORT_THRESHOLD
3662 if (send_threshold == 0)
3663 {
3664 actual_threshold = 0;
3665 warning("Threshold test deactivated.");
3666 }
3667 else
3668 {
3669 actual_threshold = send_threshold / numupdates;
3670 if (actual_threshold < 60)
3671 { /* my low value */
3672 actual_threshold = 60; /* means: 1 SP_S_PLAYER+SP_S_YOU + 16 bytes */
3673 sprintf(buf, "Threshold set to %d . %d / Update(Server limit!)",
3674 numupdates * 60, 60);
3675 warning(buf);
3676 }
3677 else
3678 {
3679 sprintf(buf, "Threshold set to %d . %d / Update", send_threshold, actual_threshold);
3680 warning(buf);
3681 }
3682 }
3683 #else
3684 warning("Server is compiled without Thresholdtesting!");
3685 #endif
3686 }
3687
3688 void
3689 handleSMessageReq(packet)
3690 struct mesg_s_cpacket *packet;
3691 {
3692 /* If someone would delete the hardcoded things in handleMessageReq */
3693 /* like packet->mesg[69]='\0'; */
3694 /* we could give handleMessageReq the packet without copying */
3695 /* But i have no time HW 04/6/93 */
3696
3697 struct mesg_cpacket mesPacket;
3698 mesPacket.type = CP_MESSAGE;
3699 mesPacket.group = packet->group;
3700 mesPacket.indiv = packet->indiv;
3701 strcpy(mesPacket.mesg, packet->mesg);
3702 handleMessageReq(&mesPacket);
3703 /* I hope this was it */
3704 }
3705
3706
3707 #endif
3708
3709 /*
3710 *
3711 * ---------------------------------------------------------------------------
3712 * Strictly UDP from here on
3713 * ---------------------------------------------------------------------------
3714 * */
3715
3716 void
3717 handleUdpReq(packet)
3718 struct udp_req_cpacket *packet;
3719 {
3720 struct udp_reply_spacket response;
3721 int mode;
3722
3723 response.type = SP_UDP_REPLY;
3724
3725 if (packet->request == COMM_VERIFY)
3726 {
3727 /* this request should ONLY come through the UDP connection */
3728 if (commMode == COMM_UDP)
3729 {
3730 UDPDIAG(("Got second verify from %s; resending server verify\n",
3731 me->p_name));
3732 response.reply = SWITCH_VERIFY;
3733 goto send;
3734 }
3735 UDPDIAG(("Receieved UDP verify from %s\n", me->p_name));
3736 UDPDIAG(("--- UDP connection established to %s\n", me->p_name));
3737 #ifdef BROKEN
3738 warning("WARNING: BROKEN mode is enabled");
3739 #endif
3740
3741 resetUDPsequence(); /* reset sequence numbers */
3742 commMode = COMM_UDP; /* at last */
3743 udpMode = MODE_SIMPLE; /* just send one at a time */
3744
3745 /* note that we don't NEED to send a SWITCH_VERIFY packet; the client */
3746 /*
3747 * will change state when it receives ANY packet on the UDP connection
3748 */
3749 /* (this just makes sure that it gets one) */
3750 /* (update: recvfrom() currently tosses the first packet it gets...) */
3751 response.reply = SWITCH_VERIFY;
3752 goto send;
3753 /* return; */
3754 }
3755 if (packet->request == COMM_MODE)
3756 {
3757 /* wants to switch modes; mode is in "conmode" */
3758 mode = packet->connmode;
3759 if (mode < MODE_TCP || mode > MODE_DOUBLE)
3760 {
3761 warning("Server can't do that UDP mode");
3762 UDPDIAG(("Got bogus request for UDP mode %d from %s\n",
3763 mode, me->p_name));
3764 }
3765 else
3766 {
3767 /* I don't bother with a reply, though it can mess up the opt win */
3768 switch (mode)
3769 {
3770 case MODE_TCP:
3771 warning("Server will send with TCP only");
3772 break;
3773 case MODE_SIMPLE:
3774 warning("Server will send with simple UDP");
3775 break;
3776 case MODE_FAT:
3777 warning("Server will send with fat UDP; sent full update");
3778 V_UDPDIAG(("Sending full update to %s\n", me->p_name));
3779 forceUpdate();
3780 break;
3781 #ifdef DOUBLE_UDP
3782 case MODE_DOUBLE:
3783 warning("Server will send with double UDP");
3784 scbufptr = scbuf + sizeof(struct sc_sequence_spacket);
3785 break;
3786 #else
3787 case MODE_DOUBLE:
3788 warning("Request for double UDP DENIED (set to simple)");
3789 mode = MODE_SIMPLE;
3790 break;
3791 #endif /* DOUBLE_UDP */
3792 }
3793
3794 udpMode = mode;
3795 UDPDIAG(("Switching %s to UDP mode %d\n", me->p_name, mode));
3796 }
3797 return;
3798 }
3799 if (packet->request == COMM_UPDATE)
3800 {
3801 /* client wants a FULL update */
3802 V_UDPDIAG(("Sending full update to %s\n", me->p_name));
3803 forceUpdate();
3804
3805 return;
3806 }
3807 UDPDIAG(("Received request for %s mode from %s\n",
3808 (packet->request == COMM_TCP) ? "TCP" : "UDP", me->p_name));
3809 if (packet->request == commMode)
3810 {
3811 /* client asking to switch to current mode */
3812 if (commMode == COMM_UDP)
3813 {
3814 /*
3815 * client must be confused... whatever the cause, he obviously isn't
3816 * connected to us, so we better drop out end and retry.
3817 */
3818 UDPDIAG(("Rcvd UDP req from %s while in UDP mode; dropping old\n",
3819 me->p_name));
3820 closeUdpConn();
3821 commMode = COMM_TCP;
3822 /* ...and fall thru to the UDP request handler */
3823 }
3824 else
3825 {
3826 /*
3827 * Again, client is confused. This time there's no damage though. Just
3828 * tell him that he succeeded. Could also happen if the client tried
3829 * to connect to our UDP socket but failed, and decided to back off.
3830 */
3831 UDPDIAG(("Rcvd TCP req from %s while in TCP mode\n", me->p_name));
3832
3833 response.reply = SWITCH_TCP_OK;
3834 sendClientPacket((struct player_spacket *) & response);
3835
3836 if (udpSock >= 0)
3837 {
3838 closeUdpConn();
3839 UDPDIAG(("Closed UDP socket\n"));
3840 }
3841 return;
3842 }
3843 }
3844 /* okay, we have a request to change modes */
3845 if (packet->request == COMM_UDP)
3846 {
3847 udpClientPort = ntohl(packet->port); /* where to connect to */
3848 if (!configvals->udpAllowed)
3849 {
3850 UDPDIAG(("Rejected UDP request from %s\n", me->p_name));
3851 response.reply = SWITCH_DENIED;
3852 response.port = htons(0);
3853 goto send;
3854 }
3855 else
3856 {
3857 if (userUdpVersion != UDPVERSION)
3858 {
3859 char buf[80];
3860 sprintf(buf, "Server UDP is v%.1f, client is v%.1f",
3861 (float) UDPVERSION / 10.0,
3862 (float) userUdpVersion / 10.0);
3863 warning(buf);
3864 UDPDIAG(("%s (rejected %s)\n", buf, me->p_name));
3865 response.reply = SWITCH_DENIED;
3866 response.port = htons(1);
3867 goto send;
3868 }
3869 if (udpSock >= 0)
3870 {
3871 /* we have a socket open, but the client doesn't seem aware */
3872 /* (probably because our UDP verify got lost down the line) */
3873 UDPDIAG(("Receieved second request from %s, reconnecting\n",
3874 me->p_name));
3875 closeUdpConn();
3876 }
3877 /* (note no openUdpConn(); we go straight to connect) */
3878 if (connUdpConn() < 0)
3879 {
3880 response.reply = SWITCH_DENIED;
3881 response.port = 0;
3882 goto send;
3883 }
3884 UDPDIAG(("Connected UDP socket (%d:%d) for %s\n", udpSock,
3885 udpLocalPort, me->p_name));
3886
3887 /* we are now connected to the client, but he's merely bound */
3888 /* don't switch to UDP mode yet; wait until client connects */
3889 response.reply = SWITCH_UDP_OK;
3890 response.port = htonl(udpLocalPort);
3891
3892 UDPDIAG(("packet->connmode = %d\n", packet->connmode));
3893 if (packet->connmode == CONNMODE_PORT)
3894 {
3895 /* send him our port # so he can connect to us */
3896 goto send;
3897 }
3898 else
3899 { /* send him a packet; he'll get port from
3900 * recvfrom() */
3901 int t = sizeof(response);
3902 if (gwrite(udpSock, (char *) &response, sizeof(response)) != t)
3903 {
3904 UDPDIAG(("Attempt to send UDP packet failed; using alt\n"));
3905 }
3906 goto send;
3907 }
3908
3909 }
3910 }
3911 else if (packet->request == COMM_TCP)
3912 {
3913 closeUdpConn();
3914 commMode = COMM_TCP;
3915 response.reply = SWITCH_TCP_OK;
3916 response.port = 0;
3917 UDPDIAG(("Closed UDP socket for %s\n", me->p_name));
3918 goto send;
3919 }
3920 else
3921 {
3922 fprintf(stderr, "ntserv: got weird UDP request (%d)\n",
3923 packet->request);
3924 return;
3925 }
3926 send:
3927 sendClientPacket((struct player_spacket *) & response);
3928 }
3929
3930
3931 int
3932 connUdpConn()
3933 {
3934 struct sockaddr_in addr;
3935 int len;
3936
3937 if (udpSock > 0)
3938 {
3939 fprintf(stderr, "ntserv: tried to open udpSock twice\n");
3940 return (0); /* pretend we succeeded (this could be bad) */
3941 }
3942 resetUDPbuffer();
3943 if ((udpSock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
3944 {
3945 perror("ntserv: unable to create DGRAM socket");
3946 return (-1);
3947 }
3948 addr.sin_family = AF_INET;
3949 addr.sin_addr.s_addr = remoteaddr; /* addr of our client */
3950 addr.sin_port = htons(udpClientPort); /* client's port */
3951
3952 if (connect(udpSock, (struct sockaddr *) & addr, sizeof(addr)) < 0)
3953 {
3954 perror("ntserv: connect to client UDP port");
3955 UDPDIAG(("Unable to connect() to %s on port %d\n", me->p_name,
3956 udpClientPort));
3957 close(udpSock);
3958 udpSock = -1;
3959 return (-1);
3960 }
3961 UDPDIAG(("connect to %s's port %d on 0x%x succeded\n",
3962 me->p_name, udpClientPort, remoteaddr));
3963
3964 /* determine what our port is */
3965 len = sizeof(addr);
3966 if (getsockname(udpSock, (struct sockaddr *) & addr, &len) < 0)
3967 {
3968 perror("netrek: unable to getsockname(UDP)");
3969 UDPDIAG(("Can't get our own socket; connection failed\n"));
3970 close(udpSock);
3971 udpSock = -1;
3972 return (-1);
3973 }
3974 udpLocalPort = (int) ntohs(addr.sin_port);
3975
3976 if (configvals->udpAllowed > 2) /* verbose debug mode? */
3977 printUdpInfo();
3978
3979 return (0);
3980 }
3981
3982 int
3983 closeUdpConn()
3984 {
3985 V_UDPDIAG(("Closing UDP socket\n"));
3986 if (udpSock < 0)
3987 {
3988 fprintf(stderr, "ntserv: tried to close a closed UDP socket\n");
3989 return (-1);
3990 }
3991 shutdown(udpSock, 2); /* wham */
3992 close(udpSock); /* bam */
3993 udpSock = -1; /* (nah) */
3994
3995 return (0);
3996 }
3997
3998 /* used for debugging */
3999 void
4000 printUdpInfo()
4001 {
4002 struct sockaddr_in addr;
4003 int len;
4004
4005 len = sizeof(addr);
4006 if (getsockname(udpSock, (struct sockaddr *) & addr, &len) < 0)
4007 {
4008 perror("printUdpInfo: getsockname");
4009 return;
4010 }
4011 UDPDIAG(("LOCAL: addr=0x%lx, family=%d, port=%d\n",
4012 (u_long) addr.sin_addr.s_addr,
4013 addr.sin_family, ntohs(addr.sin_port)));
4014
4015 if (getpeername(udpSock, (struct sockaddr *) & addr, &len) < 0)
4016 {
4017 perror("printUdpInfo: getpeername");
4018 return;
4019 }
4020 UDPDIAG(("PEER : addr=0x%lx, family=%d, port=%d\n",
4021 (u_long) addr.sin_addr.s_addr,
4022 addr.sin_family, ntohs(addr.sin_port)));
4023 }
4024
4025 void
4026 handleSequence()
4027 {
4028 /* we don't currently deal with sequence numbers from clients */
4029 }
4030
4031 void
4032 handleAskMOTD()
4033 {
4034 sendMotd();
4035 }
4036
4037
4038 #ifdef DOUBLE_UDP
4039 /*
4040 * If we're in double-UDP mode, then we need to send a separate semi-critical
4041 * transmission over UDP. We need to give it the same sequence number as the
4042 * previous transmission, but the sequence packet will have type
4043 * SP_CP_SEQUENCE instead of SP_SEQUENCE.
4044 */
4045 void
4046 sendSC()
4047 {
4048 struct sequence_spacket *ssp;
4049 struct sc_sequence_spacket *sc_sp;
4050 int cc;
4051
4052 if (commMode != COMM_UDP || udpMode != MODE_DOUBLE)
4053 {
4054 /* mode not active, keep buffer clear */
4055 scbufptr = scbuf;
4056 return;
4057 }
4058 if (scbufptr - scbuf <= sizeof(struct sc_sequence_spacket))
4059 {
4060 /* nothing to send */
4061 return;
4062 }
4063 /* copy sequence #, send what we got, then reset buffer */
4064 sc_sp = (struct sc_sequence_spacket *) scbuf;
4065 ssp = (struct sequence_spacket *) udpbuf;
4066 sc_sp->type = SP_SC_SEQUENCE;
4067 sc_sp->sequence = ssp->sequence;
4068 if ((cc = gwrite(udpSock, scbuf, scbufptr - scbuf)) != scbufptr - scbuf)
4069 {
4070 fprintf(stderr, "UDP sc gwrite failed (%d, error %d)\n", cc, errno);
4071 UDPDIAG(("*** UDP diSConnected for %s\n", me->p_name));
4072 printUdpInfo();
4073 closeUdpConn();
4074 commMode = COMM_TCP;
4075 return;
4076 }
4077 scbufptr = scbuf + sizeof(struct sc_sequence_spacket);
4078 }
4079
4080 #endif
4081
4082 /*
4083 * This is a truncated version of initClientData(). Note that it doesn't
4084 * explicitly reset all the fat UDP stuff; sendClientData will take care of
4085 * that by itself eventually.
4086 *
4087 * Only semi-critical data is sent, with a few exceptions for non-critical data
4088 * which would be nice to update (stats, kills, player posn, etc). The
4089 * critical stuff can't be lost, so there's no point in resending it.
4090 *
4091 * (Since the fat data begins in an unqueued state, forceUpdate() should be
4092 * called immediately after switching to fat mode. This guarantees that
4093 * every packet will end up on a queue. The only real reason for doing this
4094 * is so that switching to fat mode will clear up your display and keep it
4095 * cleared; otherwise you could have torps floating around forever because
4096 * the packet for them isn't on a queue. Will it reduce the effectiveness of
4097 * fat UDP? No, because as soon as the player hits the "update all" key it's
4098 * gonna happen anyway...)
4099 */
4100 void
4101 forceUpdate()
4102 {
4103 static time_t lastone = 0;
4104 time_t now;
4105 int i;
4106
4107 now = time(0);
4108 if (now - lastone < UDP_UPDATE_WAIT)
4109 {
4110 warning("Update request DENIED (chill out!)");
4111 return;
4112 }
4113 lastone = now;
4114
4115 /* clientDead=0; */
4116 for (i = 0; i < MAXPLAYER; i++)
4117 {
4118 clientHostile[i].hostile = -1;
4119 clientStats[i].losses = -1; /* (non-critical, but nice) */
4120 /* clientLogin[i].rank= -1; (critical) */
4121 /* clientPlayersInfo[i].shiptype= -1; (critical) */
4122 /* clientPStatus[i].status= -1; (critical) */
4123 clientPlayers[i].x = htonl(-1); /* (non-critical, but nice) */
4124 clientPhasers[i].status = -1;
4125 clientKills[i].kills = htonl(-1); /* (non-critical, but nice) */
4126 clientFlags[i].flags = htonl(-1);
4127 mustUpdate[i] = 0;
4128 }
4129 for (i = 0; i < MAXPLAYER * MAXTORP; i++)
4130 {
4131 clientTorpsInfo[i].status = -1;
4132 /* clientTorps[i].x= -1; (non-critical) */
4133 }
4134 for (i = 0; i < MAXPLAYER * MAXPLASMA; i++)
4135 {
4136 clientPlasmasInfo[i].status = -1;
4137 /* clientPlasmas[i].x= -1; (non-critical) */
4138 }
4139 for (i = 0; i < TOTALTHINGIES; i++)
4140 {
4141
4142 clientThingysInfo[i].shape = htons(-1);
4143 /* clientThingys[i].x= -1; (non-critical) */
4144 }
4145 for (i = 0; i < MAXPLANETS; i++)
4146 {
4147 clientPlanets2[i].armies = htonl(-2);
4148 /* clientPlanetLocs[i].x= htonl(-1); (critical) */
4149 }
4150 /* msgCurrent=(mctl->mc_current+1) % MAXMESSAGE; */
4151 clientSelf.pnum = -1;
4152 }
4153
4154 int
4155 isCensured(s) /* return true if cannot message opponents */
4156 char *s;
4157 {
4158 return (
4159 #if 0
4160 (strncmp(s, "am4m", 4) == 0) || /* 7/21/91 TC */
4161 (strncmp(s, "dm3e", 4) == 0) || /* 7/21/91 TC */
4162 (strncmp(s, "gusciora", 8) == 0) || /* 7/25/91 TC */
4163 (strncmp(s, "flan", 4) == 0) || /* 4/2/91 TC */
4164 (strncmp(s, "kc3b", 4) == 0) || /* 4/4/91 TC */
4165 (strncmp(s, "windom", 6) == 0) || /* 7/20/92 TC */
4166 #endif
4167 0
4168 );
4169 }
4170
4171 /* return true if you should eat message */
4172
4173 int
4174 parseIgnore(packet)
4175 struct mesg_cpacket *packet;
4176 {
4177 char *s;
4178 int who;
4179 int what;
4180 char buf[80];
4181 int noneflag;
4182
4183 /* if (packet->indiv != me->p_no) return 0; */
4184
4185 s = packet->mesg;
4186
4187 who = packet->indiv;
4188 if ((*s != ':') && (strncmp(s, " ", 5) != 0))
4189 return 0;
4190 if ((who == me->p_no) || (*s == ' '))
4191 { /* check for borg call 4/6/92 TC */
4192 if (configvals->binconfirm)
4193 warning("No cyborgs allowed in the game at this time.");
4194 else
4195 {
4196 char buf[80];
4197 char buf2[5];
4198 int i;
4199 int cybflag = 0;
4200
4201 strcpy(buf, "Possible cyborgs: ");
4202 for (i = 0; i < MAXPLAYER; i++)
4203 if ((players[i].p_status != PFREE) &&
4204 (players[i].p_stats.st_flags & ST_CYBORG))
4205 {
4206 sprintf(buf2, "%s ", twoletters(&players[i]));
4207 strcat(buf, buf2);
4208 cybflag = 1;
4209 }
4210 if (!cybflag)
4211 strcat(buf, "None");
4212 warning(buf);
4213 }
4214 if (*s != ' ') /* if not a borg call, eat msg 4/6/92 TC */
4215 return 1;
4216 else
4217 return 0; /* otherwise, send it 4/6/92 TC */
4218 }
4219 if (packet->group != MINDIV)
4220 return 0; /* below is for indiv only */
4221
4222 do
4223 {
4224 what = 0;
4225 switch (*(++s))
4226 {
4227 case 'a':
4228 case 'A':
4229 what = MALL;
4230 break;
4231 case 't':
4232 case 'T':
4233 what = MTEAM;
4234 break;
4235 case 'i':
4236 case 'I':
4237 what = MINDIV;
4238 break;
4239 case '\0':
4240 what = 0;
4241 break;
4242 default:
4243 what = 0;
4244 break;
4245 }
4246 ignored[who] ^= what;
4247 } while (what != 0);
4248
4249 strcpy(buf, "Ignore status for this player: ");
4250 noneflag = 1;
4251 if (ignored[who] & MALL)
4252 {
4253 strcat(buf, "All ");
4254 noneflag = 0;
4255 }
4256 if (ignored[who] & MTEAM)
4257 {
4258 strcat(buf, "Team ");
4259 noneflag = 0;
4260 }
4261 if (ignored[who] & MINDIV)
4262 {
4263 strcat(buf, "Indiv ");
4264 noneflag = 0;
4265 }
4266 if (noneflag)
4267 strcat(buf, "None");
4268 warning(buf);
4269 return 1;
4270 }
4271
4272 /* give session stats if you send yourself a '?' 2/27/92 TC */
4273 /* or '!' for ping stats (HAK) */
4274 /* merged RSA query '#' here, too (HAK) */
4275 /* return true if you should eat message */
4276
4277 int
4278 parseQuery(packet)
4279 struct mesg_spacket *packet; /* was cpacket 4/17/92 TC */
4280 {
4281 char buf[80];
4282 float sessionBombing, sessionPlanets, sessionOffense, sessionDefense;
4283 int deltaArmies, deltaPlanets, deltaKills, deltaLosses, deltaTicks;
4284
4285 extern int startTkills, startTlosses, startTarms, startTplanets, startTticks;
4286
4287 /* 0-8 for address, 9 is space */
4288
4289 if (packet->mesg[11] != '\0') /* one character only */
4290 return 0;
4291
4292 switch (packet->mesg[10])
4293 {
4294 case '!':
4295 return bouncePingStats(packet);
4296 case '#':
4297 sprintf(buf, "Client: %s", RSA_client_type);
4298 bounce(buf, packet->m_from);
4299 return 1;
4300 case '?':
4301 deltaPlanets = me->p_stats.st_tplanets - startTplanets;
4302 deltaArmies = me->p_stats.st_tarmsbomb - startTarms;
4303 deltaKills = me->p_stats.st_tkills - startTkills;
4304 deltaLosses = me->p_stats.st_tlosses - startTlosses;
4305 deltaTicks = me->p_stats.st_tticks - startTticks;
4306
4307 if (deltaTicks == 0)
4308 return 1; /* can happen if no tmode */
4309
4310 sessionPlanets = (float) deltaPlanets *status->timeprod /
4311 ((float) deltaTicks * status->planets);
4312
4313 sessionBombing = (float) deltaArmies *status->timeprod /
4314 ((float) deltaTicks * status->armsbomb);
4315
4316 sessionOffense = (float) deltaKills *status->timeprod /
4317 ((float) deltaTicks * status->kills);
4318
4319 sessionDefense = (float) deltaTicks *status->losses /
4320 (deltaLosses != 0 ?
4321 ((float) deltaLosses * status->timeprod) :
4322 (status->timeprod));
4323
4324 sprintf(buf, "%2s stats: %d planets and %d armies. %d wins/%d losses. %5.2f hours.",
4325 twoletters(me),
4326 deltaPlanets,
4327 deltaArmies,
4328 deltaKills,
4329 deltaLosses,
4330 (float) deltaTicks / 36000.0);
4331 bounce(buf, packet->m_from);
4332 sprintf(buf, "Ratings: Pla: %5.2f Bom: %5.2f Off: %5.2f Def: %5.2f Ratio: %4.2f",
4333 sessionPlanets,
4334 sessionBombing,
4335 sessionOffense,
4336 sessionDefense,
4337 (float) deltaKills /
4338 (float) ((deltaLosses == 0) ? 1 : deltaLosses));
4339 bounce(buf, packet->m_from);
4340 return 1;
4341 default:
4342 return 0;
4343 }
4344 /* NOTREACHED */
4345 }
4346
4347 int
4348 bouncePingStats(packet)
4349 struct mesg_spacket *packet;
4350 {
4351 char buf[80];
4352
4353 if (me->p_avrt == -1)
4354 {
4355 /* client doesn't support it or server not pinging */
4356 sprintf(buf, "No ping stats available for %s",
4357 twoletters(me));
4358 }
4359 else
4360 {
4361 sprintf(buf, "%s ping stats: Average: %d ms, Stdv: %d ms, Loss: %d%%",
4362 twoletters(me),
4363 me->p_avrt,
4364 me->p_stdv,
4365 me->p_pkls);
4366 }
4367 bounce(buf, packet->m_from);
4368
4369 return 1;
4370 }
4371
4372 /* new code, sends bouncemsg to bounceto from GOD 4/17/92 TC */
4373 void
4374 bounce(bouncemsg, bounceto)
4375 char *bouncemsg;
4376 int bounceto;
4377 {
4378 char buf[10];
4379
4380 sprintf(buf, "GOD->%s", twoletters(&players[bounceto]));
4381 pmessage(bouncemsg, bounceto, MINDIV, buf);
4382 }
4383
4384
4385 /*
4386 */
4387
4388 void
4389 sendShipCap()
4390 {
4391 struct ship_cap_spacket temppack;
4392 struct ship ship;
4393 int i;
4394
4395 if (!blk_flag)
4396 return;
4397 for (i = 0; i < NUM_TYPES; i++)
4398 {
4399 getship(&ship, i);
4400 temppack.type = SP_SHIP_CAP;
4401 temppack.operation = 0;
4402 temppack.s_type = htons(ship.s_type);
4403 temppack.s_torpspeed = htons(ship.s_torp.speed);
4404 #if 1
4405 temppack.s_phaserrange = htons(ship.s_phaser.speed);
4406 #else
4407 temppack.s_phaserrange = htons(ship.s_phaser.damage);
4408 #endif
4409 temppack.s_maxspeed = htonl(ship.s_imp.maxspeed);
4410 temppack.s_maxfuel = htonl(ship.s_maxfuel);
4411 temppack.s_maxshield = htonl(ship.s_maxshield);
4412 temppack.s_maxdamage = htonl(ship.s_maxdamage);
4413 temppack.s_maxwpntemp = htonl(ship.s_maxwpntemp);
4414 temppack.s_maxegntemp = htonl(ship.s_maxegntemp);
4415 temppack.s_width = htons(ship.s_width);
4416 temppack.s_height = htons(ship.s_height);
4417 temppack.s_maxarmies = htons(ship.s_maxarmies);
4418 temppack.s_letter = ship.s_letter;
4419 temppack.s_desig1 = ship.s_desig1;
4420 temppack.s_desig2 = ship.s_desig2;
4421 if (blk_flag == 1)
4422 temppack.s_bitmap = htons(ship.s_alttype);
4423 else
4424 temppack.s_bitmap = htons(ship.s_bitmap);
4425 sendClientPacket((struct player_spacket *) & temppack);
4426 }
4427 }
4428
4429 void
4430 sendMotdPic(x, y, bits, page, width, height)
4431 int x;
4432 int y;
4433 char *bits;
4434 int page;
4435 int width;
4436 int height;
4437 {
4438 struct motd_pic_spacket temppack;
4439 short sx, sy, sp, sw, sh;
4440 int size;
4441
4442 size = (width / 8 + (width % 8 != 0)) * height;
4443 sx = x;
4444 sy = y;
4445 sp = page;
4446 sw = width;
4447 sh = height;
4448 temppack.type = SP_MOTD_PIC;
4449 temppack.x = htons(sx);
4450 temppack.y = htons(sy);
4451 temppack.width = htons(sw);
4452 temppack.height = htons(sh);
4453 temppack.page = htons(sp);
4454 memcpy(temppack.bits, bits, size);
4455
4456 sendClientPacket((struct player_spacket *) & temppack);
4457 }
4458
4459
4460 void
4461 sendMotdNopic(x, y, page, width, height)
4462 int x;
4463 int y;
4464 int page;
4465 int width;
4466 int height;
4467 {
4468 struct pe1_missing_bitmap_spacket temppack;
4469
4470 temppack.type = SP_PARADISE_EXT1;
4471 temppack.subtype = SP_PE1_MISSING_BITMAP;
4472 temppack.page = htons((short) page);
4473 temppack.x = htons((short) x);
4474 temppack.y = htons((short) y);
4475 temppack.width = htons((short) width);
4476 temppack.height = htons((short) height);
4477
4478 sendClientPacket((struct player_spacket *) & temppack);
4479 }
4480
4481 /* tells the client how many missiles carried [BDyess] */
4482 void
4483 sendMissileNum(num)
4484 int num;
4485 {
4486
4487 /* remove the 1 || to enable missile updates [BDyess] */
4488 if (clientMissiles.num == htons(num))
4489 return;
4490
4491 clientMissiles.type = SP_PARADISE_EXT1;
4492 clientMissiles.subtype = SP_PE1_NUM_MISSILES;
4493 clientMissiles.num = htons(num);
4494
4495 sendClientPacket((struct player_spacket *) & clientMissiles);
4496 }
4497
4498 #ifdef RSA_EXEMPTION_FILE
4499
4500 /*
4501 * this code was copied from
4502 *
4503 * portname.c, part of faucet and hose: network pipe utilities Copyright (C)
4504 * 1992 Robert Forsman
4505 *
4506 * He has granted the Paradise project permission to use this code for
4507 * non-profit purposes.
4508 *
4509 */
4510
4511 int
4512 convert_hostname(char *name, struct in_addr * addr)
4513 {
4514 struct hostent *hp;
4515 int len;
4516
4517 hp = gethostbyname(name);
4518 if (hp != NULL)
4519 memcpy(addr, hp->h_addr, hp->h_length);
4520 else
4521 {
4522 int count;
4523 unsigned int a1, a2, a3, a4;
4524
4525 count = sscanf(name, "%i.%i.%i.%i%n", &a1, &a2, &a3, &a4, &len);
4526
4527 if (4 != count || 0 != name[len])
4528 return 0;
4529
4530 addr->s_addr = (((((a1 << 8) | a2) << 8) | a3) << 8) | a4;
4531 }
4532 return 1;
4533 }
4534
4535 /*
4536 * figure out if our client is exempt from RSA authentication.
4537 *
4538 * The host name resolution above doesn't handle gateways, which can have more
4539 * than one internet address :/
4540 */
4541
4542 int
4543 site_rsa_exempt()
4544 {
4545 FILE *fp;
4546 char buf[256];
4547
4548 if (remoteaddr == -1)
4549 {
4550 printf("remote address is not yet available?!\n");
4551 return 0; /* weird */
4552 }
4553
4554 /* hopefully we've got the remote address at this point */
4555
4556 fp = fopen(build_path(RSA_EXEMPTION_FILE), "r");
4557
4558 if (!fp)
4559 return 0; /* nobody is exempt */
4560
4561 while (fgets(buf, sizeof(buf), fp))
4562 {
4563 char hostname[256];
4564 char *playername;
4565 int len;
4566 int i;
4567 struct in_addr addr;
4568
4569 len = strlen(buf);
4570
4571 if (buf[len - 1] == '\n')
4572 buf[len - 1] = 0;
4573
4574 for (i = 0; buf[i] && !isspace(buf[i]); i++)
4575 hostname[i] = buf[i];
4576
4577 hostname[i] = 0; /* hostname is copied to buffer */
4578
4579 while (buf[i] && isspace(buf[i]))
4580 i++;
4581
4582 playername = buf + i; /* player name is stuff after hostname */
4583
4584 if (!(*playername == 0 || strcmp(playername, me->p_name) == 0))
4585 continue; /* name didn't match */
4586
4587 /*
4588 * shit, I gotta parse this crap myself. I'll steal this code from hose
4589 * - RF
4590 */
4591 if (!convert_hostname(hostname, &addr))
4592 {
4593 printf("address in %s unparseable `%s'\n",
4594 RSA_EXEMPTION_FILE, hostname);
4595 continue;
4596 }
4597
4598 if (addr.s_addr == remoteaddr)
4599 return 1;
4600 } /* while (line in rsa-exempt file) */
4601
4602 fclose(fp);
4603
4604 return 0;
4605 }
4606
4607 #endif /* RSA_EXEMPTION_FILE */