Mercurial > ~darius > hgwebdir.cgi > paradise_server
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 */ |