d_server.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. /* Emacs style mode select -*- C++ -*-
  2. *-----------------------------------------------------------------------------
  3. *
  4. *
  5. * PrBoom: a Doom port merged with LxDoom and LSDLDoom
  6. * based on BOOM, a modified and improved DOOM engine
  7. * Copyright (C) 1999 by
  8. * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
  9. * Copyright (C) 1999-2004 by
  10. * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
  11. * Copyright 2005, 2006 by
  12. * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version 2
  17. * of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  27. * 02111-1307, USA.
  28. *
  29. * DESCRIPTION:
  30. * Network game server code
  31. * New for LxDoom, but drawing ideas and code fragments from the
  32. * earlier net code
  33. *-----------------------------------------------------------------------------
  34. */
  35. #ifdef HAVE_CONFIG_H
  36. #include "config.h"
  37. #endif
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <time.h>
  41. #include <limits.h>
  42. #include <string.h>
  43. #ifdef HAVE_UNISTD_H
  44. #include <unistd.h>
  45. #endif
  46. #include <stdarg.h>
  47. #include <fcntl.h>
  48. #include <signal.h>
  49. #include <sys/types.h>
  50. #ifdef USE_SDL_NET
  51. #include "SDL.h"
  52. #endif
  53. #include "doomtype.h"
  54. #include "protocol.h"
  55. #include "i_network.h"
  56. #ifndef PRBOOM_SERVER
  57. #include "m_fixed.h"
  58. #endif
  59. #include "i_system.h"
  60. #include "m_swap.h"
  61. #ifndef HAVE_NET
  62. int main(void)
  63. {
  64. fprintf(stderr,
  65. PACKAGE "-server: You must compile with networking enabled!\n");
  66. exit(1);
  67. return 1;
  68. }
  69. #else
  70. #ifndef HAVE_GETOPT
  71. /* The following code for getopt is from the libc-source of FreeBSD,
  72. * it might be changed a little bit.
  73. * Florian Schulze (florian.schulze@gmx.net)
  74. */
  75. /*
  76. * Copyright (c) 1987, 1993, 1994
  77. * The Regents of the University of California. All rights reserved.
  78. *
  79. * Redistribution and use in source and binary forms, with or without
  80. * modification, are permitted provided that the following conditions
  81. * are met:
  82. * 1. Redistributions of source code must retain the above copyright
  83. * notice, this list of conditions and the following disclaimer.
  84. * 2. Redistributions in binary form must reproduce the above copyright
  85. * notice, this list of conditions and the following disclaimer in the
  86. * documentation and/or other materials provided with the distribution.
  87. * 3. All advertising materials mentioning features or use of this software
  88. * must display the following acknowledgement:
  89. * This product includes software developed by the University of
  90. * California, Berkeley and its contributors.
  91. * 4. Neither the name of the University nor the names of its contributors
  92. * may be used to endorse or promote products derived from this software
  93. * without specific prior written permission.
  94. *
  95. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  96. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  97. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  98. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  99. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  100. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  101. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  102. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  103. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  104. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  105. * SUCH DAMAGE.
  106. */
  107. #if defined(LIBC_SCCS) && !defined(lint)
  108. #if 0
  109. static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
  110. #endif
  111. static const char rcsid[] = "$FreeBSD$";
  112. #endif /* LIBC_SCCS and not lint */
  113. int opterr = 1, /* if error message should be printed */
  114. optind = 1, /* index into parent argv vector */
  115. optopt, /* character checked for validity */
  116. optreset; /* reset getopt */
  117. char *optarg; /* argument associated with option */
  118. #define BADCH (int)'?'
  119. #define BADARG (int)':'
  120. #define EMSG ""
  121. char *__progname="prboom_server";
  122. /*
  123. * getopt --
  124. * Parse argc/argv argument vector.
  125. */
  126. int
  127. getopt(nargc, nargv, ostr)
  128. int nargc;
  129. char * const *nargv;
  130. const char *ostr;
  131. {
  132. extern char *__progname;
  133. static char *place = EMSG; /* option letter processing */
  134. char *oli; /* option letter list index */
  135. int ret;
  136. if (optreset || !*place) { /* update scanning pointer */
  137. optreset = 0;
  138. if (optind >= nargc || *(place = nargv[optind]) != '-') {
  139. place = EMSG;
  140. return (-1);
  141. }
  142. if (place[1] && *++place == '-') { /* found "--" */
  143. ++optind;
  144. place = EMSG;
  145. return (-1);
  146. }
  147. } /* option letter okay? */
  148. if ((optopt = (int)*place++) == (int)':' ||
  149. !(oli = strchr(ostr, optopt))) {
  150. /*
  151. * if the user didn't specify '-' as an option,
  152. * assume it means -1.
  153. */
  154. if (optopt == (int)'-')
  155. return (-1);
  156. if (!*place)
  157. ++optind;
  158. if (opterr && *ostr != ':')
  159. (void)fprintf(stderr,
  160. "%s: illegal option -- %c\n", __progname, optopt);
  161. return (BADCH);
  162. }
  163. if (*++oli != ':') { /* don't need argument */
  164. optarg = NULL;
  165. if (!*place)
  166. ++optind;
  167. }
  168. else { /* need an argument */
  169. if (*place) /* no white space */
  170. optarg = place;
  171. else if (nargc <= ++optind) { /* no arg */
  172. place = EMSG;
  173. if (*ostr == ':')
  174. ret = BADARG;
  175. else
  176. ret = BADCH;
  177. if (opterr)
  178. (void)fprintf(stderr,
  179. "%s: option requires an argument -- %c\n",
  180. __progname, optopt);
  181. return (ret);
  182. }
  183. else /* white space */
  184. optarg = nargv[optind];
  185. place = EMSG;
  186. ++optind;
  187. }
  188. return (optopt); /* dump back option letter */
  189. }
  190. #else
  191. #include <unistd.h>
  192. #endif
  193. #define MAXPLAYERS 4
  194. #define BACKUPTICS 12
  195. // Dummies to forfill l_udp.c unused client stuff
  196. int M_CheckParm(const char* p) { p = NULL; return 1; }
  197. int myargc;
  198. char** myargv;
  199. void NORETURN I_Error(const char *error, ...) // killough 3/20/98: add const
  200. {
  201. va_list argptr;
  202. va_start(argptr,error);
  203. vfprintf(stderr,error,argptr);
  204. va_end(argptr);
  205. exit(-1);
  206. }
  207. int playerjoingame[MAXPLAYERS], playerleftgame[MAXPLAYERS];
  208. UDP_CHANNEL remoteaddr[MAXPLAYERS];
  209. enum { pc_unused, pc_connected, pc_ready, pc_confirmedready, pc_playing, pc_quit } playerstate[MAXPLAYERS];
  210. int displaycounter;
  211. boolean n_players_in_state(int n, int ps) {
  212. int i,j;
  213. for (i=j=0;i<MAXPLAYERS;i++)
  214. if (playerstate[i] == ps) j++;
  215. return (j == n);
  216. }
  217. void BroadcastPacket(packet_header_t *packet, size_t len)
  218. {
  219. int i;
  220. for (i=0; i<MAXPLAYERS; i++)
  221. if (playerstate[i] != pc_unused && playerstate[i] != pc_quit)
  222. I_SendPacketTo(packet, len, &remoteaddr[i]);
  223. }
  224. byte def_game_options[GAME_OPTIONS_SIZE] = \
  225. { // cf g_game.c:G_WriteOptions()
  226. 1, // monsters remember
  227. 1, // friction
  228. 0, // weapon recoil
  229. 1, // pushers
  230. 0, // reserved/unused
  231. 1, // player bobbing
  232. 0, 0, 0, // respawn, fast, nomonsters
  233. 1, // demo insurance
  234. 0, 0, 0, 0, // 4 bytes of random number seed
  235. 1, 0, 0, 0,
  236. 0, 128, /* distfriend */
  237. 0, 1, 1, 1, 1, 0,
  238. /* Zeroes for all compatibility stuff */
  239. };
  240. #define nosuch "NOSUCHCONFIGITEM"
  241. const char* gameopt_config_names[] = {
  242. "monsters_remember",nosuch,"weapon_recoil",nosuch,nosuch,"player_bobbing",nosuch,nosuch,nosuch,"demo_insurance",
  243. nosuch,nosuch,nosuch,nosuch, // RNG seed
  244. "monster_infighting","player_helpers",nosuch,nosuch,
  245. nosuch,nosuch, // distfriend
  246. "monster_backing","monster_avoid_hazards","monster_friction","help_friends","dog_jumping","monkeys",
  247. "comp_telefrag","comp_dropoff","comp_vile","comp_pain","comp_skull","comp_blazing","comp_doorlight","comp_model","comp_god","comp_falloff","comp_floors","comp_skymap","comp_pursuit","comp_doorstuck","comp_staylift","comp_zombie","comp_stairs","comp_infcheat","comp_zerotags","comp_moveblock","comp_respawn","comp_sound" };
  248. const int num_gameopts = sizeof gameopt_config_names / sizeof gameopt_config_names[0];
  249. int verbose;
  250. void NORETURN sig_handler(int signum)
  251. {
  252. char buf[80];
  253. I_SigString(buf,80,signum);
  254. printf("Received signal: %s\n", buf);
  255. // Any signal is fatal
  256. exit(1);
  257. }
  258. void doexit(void)
  259. {
  260. packet_header_t packet;
  261. // Send "downed" packet
  262. packet_set(&packet, PKT_DOWN, 0);
  263. BroadcastPacket(&packet, sizeof packet);
  264. }
  265. #ifndef USE_SDL_NET
  266. static void I_InitSockets(int v4port)
  267. {
  268. v4socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  269. I_SetupSocket(v4socket, v4port, AF_INET);
  270. }
  271. #else
  272. static void I_InitSockets(Uint16 port)
  273. {
  274. I_InitNetwork();
  275. udp_socket = I_Socket(port);
  276. if (!udp_socket) I_Error("I_InitSockets: failed to open UDP port %d\n",port);
  277. }
  278. #endif
  279. long int ptic(packet_header_t* p)
  280. {
  281. return doom_ntohl(p->tic);
  282. }
  283. void read_config_file(FILE* fp, struct setup_packet_s* sp)
  284. {
  285. byte* gameopt = sp->game_options;
  286. while (!feof(fp)) {
  287. char def[80];
  288. char strparm[100];
  289. if (fscanf (fp, "%79s %99[^\n]\n", def, strparm) == 2) {
  290. int v = atoi(strparm);
  291. if (!strcmp(def,"default_skill")) {
  292. if (verbose) printf("config file sets default_skill to %d\n",v);
  293. sp->skill = v-1;
  294. } else if (!strcmp(def,"default_compatibility_level")) {
  295. if (verbose) printf("config file sets compatibility_level to %d\n",v);
  296. if (v == -1) v = MAX_COMPATIBILITY_LEVEL-1; //e6y: -1 => maxcompat
  297. sp->complevel = v;
  298. } else {
  299. int i;
  300. for (i=0; i<num_gameopts; i++) {
  301. if (!!strcmp(gameopt_config_names[i],def)) continue;
  302. if (verbose) printf("config file sets %s to %d\n",def,v);
  303. gameopt[i] = v;
  304. }
  305. }
  306. }
  307. }
  308. }
  309. static int badplayer(int n) { return (n < 0 || n >= MAXPLAYERS); }
  310. int main(int argc, char** argv)
  311. {
  312. #ifndef USE_SDL_NET
  313. int localport = 5030;
  314. #else
  315. Uint16 localport = 5030;
  316. #endif
  317. int numplayers = 2, xtratics = 0, ticdup = 1;
  318. int exectics = 0; // gametics completed
  319. struct setup_packet_s setupinfo = { 2, 0, 1, 1, 1, 0, best_compatibility, 0, 0};
  320. char**wadname = NULL;
  321. char**wadget = NULL;
  322. int numwads = 0;
  323. {
  324. int opt;
  325. byte *gameopt = setupinfo.game_options;
  326. memcpy(gameopt, &def_game_options, sizeof (setupinfo.game_options));
  327. while ((opt = getopt(argc, argv, "c:t:x:p:e:l:adrfns:N:vw:")) != EOF)
  328. switch (opt) {
  329. case 'c':
  330. {
  331. FILE *cf = fopen(optarg,"r");
  332. if (!cf) { perror("fopen"); return -1; }
  333. read_config_file(cf,&setupinfo);
  334. fclose(cf);
  335. }
  336. break;
  337. case 't':
  338. if (optarg) ticdup = atoi(optarg);
  339. break;
  340. case 'x':
  341. if (optarg) xtratics = atoi(optarg);
  342. break;
  343. case 'p':
  344. if (optarg) localport = atoi(optarg);
  345. break;
  346. case 'e':
  347. if (optarg) setupinfo.episode = atoi(optarg);
  348. break;
  349. case 'l':
  350. if (optarg) setupinfo.level = atoi(optarg);
  351. break;
  352. case 'a':
  353. setupinfo.deathmatch = 2;
  354. break;
  355. case 'd':
  356. setupinfo.deathmatch = 1;
  357. break;
  358. case 'r':
  359. setupinfo.game_options[6] = 1;
  360. break;
  361. case 'f':
  362. setupinfo.game_options[7] = 1;
  363. break;
  364. case 'n':
  365. setupinfo.game_options[8] = 1;
  366. break;
  367. case 's':
  368. if (optarg) setupinfo.skill = atoi(optarg)-1;
  369. break;
  370. case 'N':
  371. if (optarg) setupinfo.players = numplayers = atoi(optarg);
  372. break;
  373. case 'v':
  374. verbose++;
  375. break;
  376. case 'w':
  377. if (optarg) {
  378. char *p;
  379. wadname = realloc(wadname, ++numwads * sizeof *wadname);
  380. wadget = realloc(wadget , numwads * sizeof *wadget );
  381. wadname[numwads-1] = strdup(optarg);
  382. if ((p = strchr(wadname[numwads-1], ','))) {
  383. *p++ = 0; wadget[numwads-1] = p;
  384. } else wadget[numwads-1] = NULL;
  385. }
  386. break;
  387. }
  388. }
  389. setupinfo.ticdup = ticdup; setupinfo.extratic = xtratics;
  390. { /* Random number seed
  391. * Mirrors the corresponding code in G_ReadOptions */
  392. int rngseed = (int)time(NULL);
  393. setupinfo.game_options[13] = rngseed & 0xff;
  394. rngseed >>= 8;
  395. setupinfo.game_options[12] = rngseed & 0xff;
  396. rngseed >>= 8;
  397. setupinfo.game_options[11] = rngseed & 0xff;
  398. rngseed >>= 8;
  399. setupinfo.game_options[10] = rngseed & 0xff;
  400. }
  401. I_InitSockets(localport);
  402. printf("Listening on port %d, waiting for %d players\n", localport, numplayers);
  403. { // no players initially
  404. int i;
  405. for (i=0; i<MAXPLAYERS; i++) {
  406. playerjoingame[i] = INT_MAX;
  407. playerleftgame[i] = 0;
  408. playerstate[i] = pc_unused;
  409. }
  410. // Print wads
  411. for (i=0; i<numwads; i++)
  412. printf("Wad %s (%s)\n", wadname[i], wadget[i] ? wadget[i] : "");
  413. }
  414. // Exit and signal handling
  415. atexit(doexit); // heh
  416. signal(SIGTERM, sig_handler);
  417. signal(SIGINT , sig_handler);
  418. #ifndef USE_SDL_NET
  419. signal(SIGQUIT, sig_handler);
  420. signal(SIGKILL, sig_handler);
  421. signal(SIGHUP , sig_handler);
  422. #endif
  423. {
  424. int remoteticfrom[MAXPLAYERS] = { 0, 0, 0, 0 };
  425. int remoteticto[MAXPLAYERS] = { 0, 0, 0, 0 };
  426. int backoffcounter[MAXPLAYERS] = { 0, 0, 0, 0 };
  427. int curplayers = 0;
  428. int confirming = 0;
  429. boolean ingame = false;
  430. ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
  431. while (1) {
  432. packet_header_t *packet = malloc(10000);
  433. size_t len;
  434. I_WaitForPacket(120*1000);
  435. while ((len = I_GetPacket(packet, 10000))) {
  436. if (verbose>2) printf("Received packet:");
  437. switch (packet->type) {
  438. case PKT_INIT:
  439. if (!ingame) {
  440. {
  441. int n;
  442. struct setup_packet_s *sinfo = (void*)(packet+1);
  443. /* Find player number and add to the game */
  444. n = *(short*)(packet+1);
  445. if (badplayer(n) || playerstate[n] != pc_unused)
  446. for (n=0; n<numplayers; n++)
  447. if (playerstate[n] == pc_unused) break;
  448. if (n == numplayers) break; // Full game
  449. playerstate[n] = pc_connected;
  450. #ifndef USE_SDL_NET
  451. remoteaddr[n] = sentfrom;
  452. #else
  453. if (sentfrom==-1)
  454. remoteaddr[n]=I_RegisterPlayer(&sentfrom_addr);
  455. #endif
  456. printf("Join by ");
  457. I_PrintAddress(stdout, &remoteaddr[n]);
  458. #ifdef USE_SDL_NET
  459. printf(" (channel %d)",remoteaddr[n]);
  460. #endif
  461. printf(" as player %d\n",n);
  462. {
  463. int i;
  464. size_t extrabytes = 0;
  465. // Send setup packet
  466. packet_set(packet, PKT_SETUP, 0);
  467. memcpy(sinfo, &setupinfo, sizeof setupinfo);
  468. sinfo->yourplayer = n;
  469. sinfo->numwads = numwads;
  470. for (i=0; i<numwads; i++) {
  471. strcpy(sinfo->wadnames + extrabytes, wadname[i]);
  472. extrabytes += strlen(wadname[i]) + 1;
  473. }
  474. I_SendPacketTo(packet, sizeof *packet + sizeof setupinfo + extrabytes,
  475. remoteaddr+n);
  476. I_uSleep(10000);
  477. I_SendPacketTo(packet, sizeof *packet + sizeof setupinfo + extrabytes,
  478. remoteaddr+n);
  479. }
  480. }
  481. }
  482. break;
  483. case PKT_GO:
  484. if (!ingame) {
  485. int from = *(byte*)(packet+1);
  486. if (badplayer(from) || playerstate[from] == pc_unused) break;
  487. if (confirming) {
  488. if (playerstate[from] != pc_confirmedready) curplayers++;
  489. playerstate[from] = pc_confirmedready;
  490. } else
  491. playerstate[from] = pc_ready;
  492. }
  493. break;
  494. case PKT_TICC:
  495. {
  496. byte tics = *(byte*)(packet+1);
  497. int from = *(((byte*)(packet+1))+1);
  498. if (badplayer(from)) break;
  499. if (verbose>2)
  500. printf("tics %ld - %ld from %d\n", ptic(packet), ptic(packet) + tics - 1, from);
  501. if (ptic(packet) > remoteticfrom[from]) {
  502. // Missed tics, so request a resend
  503. packet_set(packet, PKT_RETRANS, remoteticfrom[from]);
  504. I_SendPacketTo(packet, sizeof *packet, remoteaddr+from);
  505. } else {
  506. ticcmd_t *newtic = (void*)(((byte*)(packet+1))+2);
  507. if (ptic(packet) + tics < remoteticfrom[from]) break; // Won't help
  508. remoteticfrom[from] = ptic(packet);
  509. while (tics--)
  510. netcmds[from][remoteticfrom[from]++%BACKUPTICS] = *newtic++;
  511. }
  512. }
  513. break;
  514. case PKT_RETRANS:
  515. {
  516. int from = *(byte*)(packet+1);
  517. if (badplayer(from)) break;
  518. if (verbose>2) printf("%d requests resend from %d\n", from, ptic(packet));
  519. remoteticto[from] = ptic(packet);
  520. }
  521. break;
  522. case PKT_QUIT:
  523. {
  524. int from = *(byte*)(packet+1);
  525. if (badplayer(from)) break;
  526. if (!ingame && playerstate[from] != pc_unused) {
  527. // If we already got a PKT_GO, we have to remove this player frmo the count of ready players. And we then flag this player slot as vacant.
  528. printf("player %d pulls out\n", from);
  529. if (playerstate[from] == pc_confirmedready) curplayers--;
  530. playerstate[from] = pc_unused;
  531. } else
  532. if (playerleftgame[from] == INT_MAX) { // In the game
  533. playerleftgame[from] = ptic(packet);
  534. --curplayers;
  535. if (verbose) printf("%d quits at %d (%d left)\n", from, ptic(packet),curplayers);
  536. if (ingame && !curplayers) exit(0); // All players have exited
  537. }
  538. }
  539. // Fall through and broadcast it
  540. case PKT_EXTRA:
  541. BroadcastPacket(packet, len);
  542. if (packet->type == PKT_EXTRA) {
  543. if (verbose>2) printf("misc from %d\n", *(((byte*)(packet+1))+1));
  544. }
  545. break;
  546. case PKT_WAD:
  547. {
  548. int i;
  549. int from = *(byte*)(packet+1);
  550. char *name = 1 + (char*)(packet+1);
  551. size_t size = sizeof(packet_header_t);
  552. packet_header_t *reply;
  553. if (badplayer(from) || playerstate[from] != pc_unused) break;
  554. if (verbose) printf("Request for %s ", name);
  555. for (i=0; i<numwads; i++)
  556. if (!strcasecmp(name, wadname[i]))
  557. break;
  558. if ((i==numwads) || !wadget[i]) {
  559. if (verbose) printf("n/a\n");
  560. *(char*)(packet+1) = 0;
  561. I_SendPacketTo(packet, size+1, remoteaddr + from);
  562. } else {
  563. size += strlen(wadname[i]) + strlen(wadget[i]) + 2;
  564. reply = malloc(size);
  565. packet_set(reply, PKT_WAD, 0);
  566. strcpy((char*)(reply+1), wadname[i]);
  567. strcpy((char*)(reply+1) + strlen(wadname[i]) + 1, wadget[i]);
  568. printf("sending %s\n", wadget[i]);
  569. I_SendPacketTo(reply, size, remoteaddr + from);
  570. free(reply);
  571. }
  572. }
  573. break;
  574. default:
  575. printf("Unrecognised packet type %d\n", packet->type);
  576. break;
  577. }
  578. }
  579. free(packet);
  580. if (!ingame && n_players_in_state(numplayers,pc_confirmedready)) {
  581. int i;
  582. packet_header_t gopacket;
  583. packet = &gopacket;
  584. ingame=true;
  585. printf("All players joined, beginning game.\n");
  586. for (i=0; i<MAXPLAYERS; i++) {
  587. if (playerstate[i] == pc_confirmedready) {
  588. playerjoingame[i] = 0;
  589. playerleftgame[i] = INT_MAX;
  590. playerstate[i] = pc_playing;
  591. }
  592. }
  593. packet_set(packet, PKT_GO, 0);
  594. BroadcastPacket(packet, sizeof *packet);
  595. I_uSleep(10000);
  596. BroadcastPacket(packet, sizeof *packet);
  597. I_uSleep(10000);
  598. }
  599. if (confirming && !--confirming && !ingame) {
  600. int i;
  601. curplayers = 0;
  602. for (i=0; i<MAXPLAYERS; i++) {
  603. if (playerstate[i] == pc_ready) {
  604. playerstate[i] = pc_unused;
  605. printf("Player %d dropped, no PKT_GO received in confirmation\n", i);
  606. }
  607. if (playerstate[i] == pc_confirmedready) playerstate[i] = pc_ready;
  608. }
  609. }
  610. if (!ingame && n_players_in_state(numplayers,pc_ready)) {
  611. printf("All players ready, now confirming.\n");
  612. confirming = 100;
  613. }
  614. if (ingame) { // Run some tics
  615. int lowtic = INT_MAX;
  616. int i;
  617. for (i=0; i<MAXPLAYERS; i++)
  618. if (playerstate[i] == pc_playing || playerstate[i] == pc_quit) {
  619. if (remoteticfrom[i] < playerleftgame[i]-1 && remoteticfrom[i]<lowtic)
  620. lowtic = remoteticfrom[i];
  621. }
  622. if (verbose>1) printf("%d new tics can be run\n", lowtic - exectics);
  623. if (lowtic > exectics)
  624. exectics = lowtic; // count exec'ed tics
  625. // Now send all tics up to lowtic
  626. for (i=0; i<MAXPLAYERS; i++)
  627. if (playerstate[i] == pc_playing) {
  628. int tics;
  629. if (lowtic <= remoteticto[i]) continue;
  630. if ((remoteticto[i] -= xtratics) < 0) remoteticto[i] = 0;
  631. tics = lowtic - remoteticto[i];
  632. {
  633. byte *p;
  634. packet = malloc(sizeof(packet_header_t) + 1 +
  635. tics * (1 + numplayers * (1 + sizeof(ticcmd_t))));
  636. p = (void*)(packet+1);
  637. packet_set(packet, PKT_TICS, remoteticto[i]);
  638. *p++ = tics;
  639. if (verbose>1) printf("sending %d tics to %d\n", tics, i);
  640. while (tics--) {
  641. int j, playersthistic = 0;
  642. byte *q = p++;
  643. for (j=0; j<MAXPLAYERS; j++)
  644. if ((playerjoingame[j] <= remoteticto[i]) &&
  645. (playerleftgame[j] > remoteticto[i])) {
  646. *p++ = j;
  647. memcpy(p, &netcmds[j][remoteticto[i]%BACKUPTICS], sizeof(ticcmd_t));
  648. p += sizeof(ticcmd_t);
  649. playersthistic++;
  650. }
  651. *q = playersthistic;
  652. remoteticto[i]++;
  653. }
  654. I_SendPacketTo(packet, p - ((byte*)packet), remoteaddr+i);
  655. free(packet);
  656. }
  657. {
  658. if (remoteticfrom[i] == remoteticto[i]) {
  659. backoffcounter[i] = 0;
  660. } else if (remoteticfrom[i] > remoteticto[i]+1) {
  661. if ((backoffcounter[i] += remoteticfrom[i] - remoteticto[i] - 1) > 35) {
  662. packet_header_t *packet = malloc(sizeof(packet_header_t));
  663. packet_set(packet, PKT_BACKOFF, remoteticto[i]);
  664. I_SendPacketTo(packet,sizeof *packet,remoteaddr+i);
  665. backoffcounter[i] = 0;
  666. if (verbose) printf("telling client %d to back off\n",i);
  667. free(packet);
  668. }
  669. }
  670. }
  671. }
  672. }
  673. if (!((ingame ? 0xff : 0xf) & displaycounter++)) {
  674. int i;
  675. fprintf(stderr,"Player states: [");
  676. for (i=0;i<MAXPLAYERS;i++) {
  677. switch (playerstate[i]) {
  678. case pc_unused: fputc(' ',stderr); break;
  679. case pc_connected: fputc('c',stderr); break;
  680. case pc_ready: fputc('r',stderr); break;
  681. case pc_confirmedready: fputc('g',stderr); break;
  682. case pc_playing: fputc('p',stderr); break;
  683. case pc_quit: fputc('x',stderr); break;
  684. }
  685. }
  686. fprintf(stderr,"]\n");
  687. }
  688. }
  689. }
  690. }
  691. #endif // HAVE_NET