|
|
1.1 ! root 1: ! 2: // I_pcnet.m ! 3: // ! 4: // Modified 12-21-94 by Chris Rhinehart for use with multiple ticdups ! 5: // actually, it wasn't modified, but rather we are currently using this ! 6: // older version of D_NET.C, since the new one doesn't seem to work with ! 7: // ticdup set to greater than one. ! 8: ! 9: #include "DoomDef.h" ! 10: #include "P_local.h" ! 11: #include "soundst.h" ! 12: ! 13: #define NCMD_EXIT 0x80000000 ! 14: #define NCMD_RETRANSMIT 0x40000000 ! 15: #define NCMD_SETUP 0x20000000 ! 16: #define NCMD_CHECKSUM 0x0fffffff ! 17: ! 18: /* ! 19: if more space needs to be crunched out of the protocol... ! 20: ! 21: 1 drone ! 22: 2 player ! 23: 8 tic ! 24: 5 numtics ! 25: ! 26: #define NCMD_EXIT 0x80000000 ! 27: #define NCMD_RETRANSMIT 0x40000000 // a retransmit will have 0 tics ! 28: #define NCMD_DRONE 0x20000000 ! 29: #define NCMD_PLAYER 0x18000000 ! 30: #define NCMD_PLAYERSHIFT 27 ! 31: #define NCMD_TIC 0x00ff0000 ! 32: #define NCMD_TICSHIFT 16 ! 33: #define NCMD_NUMTICS 0x0000ff00 ! 34: #define NCMD_NUMTICSSHIFT 8 ! 35: #define NCMD_CHECKSUM 0x000000ff ! 36: ! 37: */ ! 38: ! 39: ! 40: ! 41: ! 42: ! 43: doomcom_t *doomcom; ! 44: doomdata_t *netbuffer; // points inside doomcom ! 45: ! 46: ! 47: /* ! 48: ============================================================================== ! 49: ! 50: NETWORKING ! 51: ! 52: gametic is the tic about to (or currently being) run ! 53: maketic is the tick that hasn't had control made for it yet ! 54: nettics[] has the maketics for all players ! 55: ! 56: a gametic cannot be run until nettics[] > gametic for all players ! 57: ! 58: ============================================================================== ! 59: */ ! 60: ! 61: #define RESENDCOUNT 10 ! 62: #define PL_DRONE 0x80 // bit flag in doomdata->player ! 63: ! 64: ticcmd_t localcmds[BACKUPTICS]; ! 65: ! 66: ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS]; ! 67: int nettics[MAXNETNODES]; ! 68: boolean nodeingame[MAXNETNODES]; // set false as nodes leave game ! 69: boolean remoteresend[MAXNETNODES]; // set when local needs tics ! 70: int resendto[MAXNETNODES]; // set when remote needs tics ! 71: int resendcount[MAXNETNODES]; ! 72: ! 73: int nodeforplayer[MAXPLAYERS]; ! 74: ! 75: int gametime; ! 76: int maketic; ! 77: int lastnettic, skiptics; ! 78: int ticdup; ! 79: ! 80: void D_ProcessEvents (void); ! 81: void G_BuildTiccmd (ticcmd_t *cmd); ! 82: void D_DoAdvanceDemo (void); ! 83: ! 84: boolean reboundpacket; ! 85: doomdata_t reboundstore; ! 86: ! 87: ! 88: int NetbufferSize (void) ! 89: { ! 90: return (int)&(((doomdata_t *)0)->cmds[netbuffer->numtics]); ! 91: } ! 92: ! 93: unsigned NetbufferChecksum (void) ! 94: { ! 95: unsigned c; ! 96: int i,l; ! 97: ! 98: c = 0x1234567; ! 99: ! 100: l = (NetbufferSize () - (int)&(((doomdata_t *)0)->retransmitfrom))/4; ! 101: for (i=0 ; i<l ; i++) ! 102: c += ((unsigned *)&netbuffer->retransmitfrom)[i] * (i+1); ! 103: ! 104: return c & NCMD_CHECKSUM; ! 105: } ! 106: ! 107: int ExpandTics (int low) ! 108: { ! 109: int delta; ! 110: ! 111: delta = low - (maketic&0xff); ! 112: ! 113: if (delta >= -64 && delta <= 64) ! 114: return (maketic&~0xff) + low; ! 115: if (delta > 64) ! 116: return (maketic&~0xff) - 256 + low; ! 117: if (delta < -64) ! 118: return (maketic&~0xff) + 256 + low; ! 119: ! 120: I_Error ("ExpandTics: strange value %i at maketic %i",low,maketic); ! 121: return 0; ! 122: } ! 123: ! 124: ! 125: //============================================================================ ! 126: ! 127: ! 128: /* ! 129: ============== ! 130: = ! 131: = HSendPacket ! 132: = ! 133: ============== ! 134: */ ! 135: ! 136: void HSendPacket (int node, int flags) ! 137: { ! 138: netbuffer->checksum = NetbufferChecksum () | flags; ! 139: ! 140: if (!node) ! 141: { ! 142: reboundstore = *netbuffer; ! 143: reboundpacket = true; ! 144: return; ! 145: } ! 146: ! 147: if (!netgame) ! 148: I_Error ("Tried to transmit to another node"); ! 149: ! 150: doomcom->command = CMD_SEND; ! 151: doomcom->remotenode = node; ! 152: doomcom->datalength = NetbufferSize (); ! 153: ! 154: if (debugfile) ! 155: { ! 156: int i; ! 157: int realretrans; ! 158: if (netbuffer->checksum & NCMD_RETRANSMIT) ! 159: realretrans = ExpandTics (netbuffer->retransmitfrom); ! 160: else ! 161: realretrans = -1; ! 162: fprintf (debugfile,"send (%i + %i, R %i) [%i] " ! 163: ,ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength); ! 164: for (i=0 ; i<doomcom->datalength ; i++) ! 165: fprintf (debugfile,"%i ",((byte *)netbuffer)[i]); ! 166: fprintf (debugfile,"\n"); ! 167: } ! 168: ! 169: I_NetCmd (); ! 170: } ! 171: ! 172: /* ! 173: ============== ! 174: = ! 175: = HGetPacket ! 176: = ! 177: = Returns false if no packet is waiting ! 178: = ! 179: ============== ! 180: */ ! 181: ! 182: boolean HGetPacket (void) ! 183: { ! 184: if (reboundpacket) ! 185: { ! 186: *netbuffer = reboundstore; ! 187: doomcom->remotenode = 0; ! 188: reboundpacket = false; ! 189: return true; ! 190: } ! 191: ! 192: if (!netgame) ! 193: return false; ! 194: ! 195: doomcom->command = CMD_GET; ! 196: I_NetCmd (); ! 197: if (doomcom->remotenode == -1) ! 198: return false; ! 199: ! 200: if (doomcom->datalength != NetbufferSize ()) ! 201: { ! 202: if (debugfile) ! 203: fprintf (debugfile,"bad packet length %i\n",doomcom->datalength); ! 204: return false; ! 205: } ! 206: ! 207: if (NetbufferChecksum () != (netbuffer->checksum&NCMD_CHECKSUM) ) ! 208: { ! 209: if (debugfile) ! 210: fprintf (debugfile,"bad packet checksum\n"); ! 211: return false; ! 212: } ! 213: ! 214: if (debugfile) ! 215: { ! 216: int realretrans; ! 217: int i; ! 218: ! 219: if (netbuffer->checksum & NCMD_SETUP) ! 220: fprintf (debugfile,"setup packet\n"); ! 221: else ! 222: { ! 223: if (netbuffer->checksum & NCMD_RETRANSMIT) ! 224: realretrans = ExpandTics (netbuffer->retransmitfrom); ! 225: else ! 226: realretrans = -1; ! 227: fprintf (debugfile,"get %i = (%i + %i, R %i)[%i] ",doomcom->remotenode, ! 228: ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength); ! 229: for (i=0 ; i<doomcom->datalength ; i++) ! 230: fprintf (debugfile,"%i ",((byte *)netbuffer)[i]); ! 231: fprintf (debugfile,"\n"); ! 232: } ! 233: } ! 234: return true; ! 235: } ! 236: ! 237: ! 238: /* ! 239: =================== ! 240: = ! 241: = GetPackets ! 242: = ! 243: =================== ! 244: */ ! 245: ! 246: char exitmsg[80]; ! 247: ! 248: void GetPackets (void) ! 249: { ! 250: int netconsole; ! 251: int netnode; ! 252: int netdrone; ! 253: int j; ! 254: ticcmd_t *src, *dest; ! 255: int dupedstart, dupedend; ! 256: int skiptics; ! 257: int realstart; ! 258: ! 259: while (HGetPacket ()) ! 260: { ! 261: if (netbuffer->checksum & NCMD_SETUP) ! 262: continue; // extra setup packet ! 263: ! 264: netdrone = netbuffer->player & PL_DRONE; ! 265: netconsole = netbuffer->player & ~PL_DRONE; ! 266: netnode = doomcom->remotenode; ! 267: // ! 268: // to save bytes, only the low byte of tic numbers are sent ! 269: // Figure out what the rest of the bytes are ! 270: // ! 271: realstart = ExpandTics (netbuffer->starttic); ! 272: dupedstart = realstart*doomcom->ticdup; ! 273: dupedend = (realstart+netbuffer->numtics)*doomcom->ticdup; ! 274: ! 275: // ! 276: // check for exiting the game ! 277: // ! 278: if (netbuffer->checksum & NCMD_EXIT) ! 279: { ! 280: if (!nodeingame[netnode]) ! 281: continue; ! 282: nodeingame[netnode] = false; ! 283: if (!netdrone) ! 284: { ! 285: playeringame[netconsole] = false; ! 286: strcpy (exitmsg, "PLAYER 1 HAS LEFT THE GAME"); ! 287: exitmsg[7] += netconsole; ! 288: P_SetMessage(&players[consoleplayer], exitmsg, true); ! 289: UpdateState |= I_MESSAGES; ! 290: S_StartSound(NULL, sfx_chat); ! 291: } ! 292: continue; ! 293: } ! 294: ! 295: // ! 296: // drone packets are just notifications ! 297: // ! 298: if (netdrone) ! 299: { ! 300: nettics[netnode] = dupedend; ! 301: continue; ! 302: } ! 303: ! 304: nodeforplayer[netconsole] = netnode; ! 305: ! 306: // ! 307: // check for retransmit request ! 308: // ! 309: if ( resendcount[netnode] <= 0 ! 310: && (netbuffer->checksum & NCMD_RETRANSMIT) ) ! 311: { ! 312: resendto[netnode] = ExpandTics(netbuffer->retransmitfrom); ! 313: if (debugfile) ! 314: fprintf (debugfile,"retransmit from %i\n", resendto[netnode]); ! 315: resendcount[netnode] = RESENDCOUNT; ! 316: } ! 317: else ! 318: resendcount[netnode]--; ! 319: ! 320: // ! 321: // check for out of order / duplicated packet ! 322: // ! 323: if (dupedend == nettics[netnode]) ! 324: continue; ! 325: ! 326: if (dupedend < nettics[netnode]) ! 327: { ! 328: if (debugfile) ! 329: fprintf (debugfile,"out of order packet (%i + %i)\n" ,realstart,netbuffer->numtics); ! 330: continue; ! 331: } ! 332: ! 333: // ! 334: // check for a missed packet ! 335: // ! 336: if (dupedstart > nettics[netnode]) ! 337: { ! 338: // stop processing until the other system resends the missed tics ! 339: if (debugfile) ! 340: fprintf (debugfile,"missed tics from %i (%i - %i)\n", netnode, dupedstart, nettics[netnode]); ! 341: remoteresend[netnode] = true; ! 342: continue; ! 343: } ! 344: ! 345: // ! 346: // update command store from the packet ! 347: // ! 348: remoteresend[netnode] = false; ! 349: ! 350: skiptics = nettics[netnode]/doomcom->ticdup - realstart; ! 351: src = &netbuffer->cmds[skiptics]; ! 352: ! 353: while (nettics[netnode] < dupedend) ! 354: { ! 355: for (j=0 ; j<doomcom->ticdup ; j++) ! 356: { ! 357: dest = &netcmds[netconsole][nettics[netnode]%BACKUPTICS]; ! 358: nettics[netnode]++; ! 359: *dest = *src; ! 360: src->chatchar = 0; ! 361: if (src->buttons & BT_SPECIAL) ! 362: src->buttons = 0; ! 363: } ! 364: src++; ! 365: } ! 366: } ! 367: } ! 368: ! 369: /* ! 370: ============= ! 371: = ! 372: = NetUpdate ! 373: = ! 374: = Builds ticcmds for console player ! 375: = sends out a packet ! 376: ============= ! 377: */ ! 378: ! 379: void NetUpdate (void) ! 380: { ! 381: int nowtime; ! 382: int newtics; ! 383: int i,j; ! 384: int gameticdiv; ! 385: int realstart; ! 386: ! 387: if (singletics) ! 388: return; // singletic update is syncronous ! 389: ! 390: // ! 391: // check time ! 392: // ! 393: nowtime = I_GetTime ()/doomcom->ticdup; ! 394: newtics = nowtime - gametime; ! 395: gametime = nowtime; ! 396: if (newtics <= 0) // nothing new to update ! 397: goto listen; ! 398: ! 399: if (skiptics <= newtics) ! 400: { ! 401: newtics -= skiptics; ! 402: skiptics = 0; ! 403: } ! 404: else ! 405: { ! 406: skiptics -= newtics; ! 407: newtics = 0; ! 408: } ! 409: ! 410: ! 411: netbuffer->player = consoleplayer; ! 412: if (doomcom->drone) ! 413: netbuffer->player |= PL_DRONE; ! 414: ! 415: // ! 416: // drone packets ! 417: // ! 418: if (doomcom->drone) ! 419: { ! 420: I_StartTic (); ! 421: D_ProcessEvents (); ! 422: goto sendit; ! 423: } ! 424: ! 425: // ! 426: // build new ticcmds for console player ! 427: // ! 428: gameticdiv = (gametic+doomcom->ticdup-1)/doomcom->ticdup; ! 429: for (i=0 ; i<newtics ; i++) ! 430: { ! 431: I_StartTic (); ! 432: D_ProcessEvents (); ! 433: if (maketic - gameticdiv >= BACKUPTICS/2 /* /doomcom->ticdup */- 1) ! 434: { ! 435: newtics = i; ! 436: break; // can't hold any more ! 437: } ! 438: //printf ("mk:%i ",maketic); ! 439: G_BuildTiccmd (&localcmds[maketic%BACKUPTICS]); ! 440: maketic++; ! 441: } ! 442: ! 443: // ! 444: // send the packet to the other nodes ! 445: // ! 446: sendit: ! 447: for (i=0 ; i<doomcom->numnodes ; i++) ! 448: if (nodeingame[i]) ! 449: { ! 450: if (doomcom->drone) ! 451: { ! 452: netbuffer->starttic = realstart = maketic + BACKUPTICS/2; ! 453: netbuffer->numtics = 0; ! 454: } ! 455: else ! 456: { ! 457: netbuffer->starttic = realstart = resendto[i]; ! 458: netbuffer->numtics = maketic - realstart; ! 459: resendto[i] = maketic - doomcom->extratics; ! 460: } ! 461: ! 462: if (netbuffer->numtics > BACKUPTICS) ! 463: I_Error ("NetUpdate: netbuffer->numtics > BACKUPTICS"); ! 464: ! 465: for (j=0 ; j< netbuffer->numtics ; j++) ! 466: netbuffer->cmds[j] = ! 467: localcmds[(realstart+j)%BACKUPTICS]; ! 468: ! 469: if (remoteresend[i]) ! 470: { ! 471: netbuffer->retransmitfrom = nettics[i]/doomcom->ticdup; ! 472: HSendPacket (i, NCMD_RETRANSMIT); ! 473: } ! 474: else ! 475: { ! 476: netbuffer->retransmitfrom = 0; ! 477: HSendPacket (i, 0); ! 478: } ! 479: } ! 480: ! 481: // ! 482: // listen for other packets ! 483: // ! 484: listen: ! 485: ! 486: GetPackets (); ! 487: } ! 488: ! 489: ! 490: /* ! 491: ===================== ! 492: = ! 493: = CheckAbort ! 494: = ! 495: ===================== ! 496: */ ! 497: ! 498: void CheckAbort (void) ! 499: { ! 500: event_t *ev; ! 501: ! 502: I_WaitVBL(2); ! 503: ! 504: I_StartTic (); ! 505: for ( ; eventtail != eventhead ! 506: ; eventtail = (++eventtail)&(MAXEVENTS-1) ) ! 507: { ! 508: ev = &events[eventtail]; ! 509: if (ev->type == ev_keydown && ev->data1 == KEY_ESCAPE) ! 510: I_Error ("Network game synchronization aborted."); ! 511: } ! 512: } ! 513: ! 514: /* ! 515: ===================== ! 516: = ! 517: = D_ArbitrateNetStart ! 518: = ! 519: ===================== ! 520: */ ! 521: ! 522: void D_ArbitrateNetStart (void) ! 523: { ! 524: int i; ! 525: boolean gotinfo[MAXNETNODES]; ! 526: ! 527: autostart = true; ! 528: memset (gotinfo,0,sizeof(gotinfo)); ! 529: ! 530: if (doomcom->consoleplayer) ! 531: { // listen for setup info from key player ! 532: //printf ("listening for network start info...\n"); ! 533: while (1) ! 534: { ! 535: CheckAbort (); ! 536: if (!HGetPacket ()) ! 537: continue; ! 538: if (netbuffer->checksum & NCMD_SETUP) ! 539: { ! 540: if (netbuffer->player != VERSION) ! 541: I_Error ("Different HERETIC versions cannot play a net game!"); ! 542: startskill = netbuffer->retransmitfrom & 15; ! 543: deathmatch = (netbuffer->retransmitfrom & 0x80) > 0; ! 544: startmap = netbuffer->starttic & 15; ! 545: startepisode = netbuffer->starttic >> 4; ! 546: return; ! 547: } ! 548: } ! 549: } ! 550: else ! 551: { // key player, send the setup info ! 552: // printf ("sending network start info...\n"); ! 553: do ! 554: { ! 555: CheckAbort (); ! 556: for (i=0 ; i<doomcom->numnodes ; i++) ! 557: { ! 558: netbuffer->retransmitfrom = startskill; ! 559: if (deathmatch) ! 560: netbuffer->retransmitfrom |= 0x80; ! 561: netbuffer->starttic = startepisode * 16 + startmap; ! 562: netbuffer->player = VERSION; ! 563: netbuffer->numtics = 0; ! 564: HSendPacket (i, NCMD_SETUP); ! 565: } ! 566: ! 567: while (HGetPacket ()) ! 568: { ! 569: //printf ("got packet\n"); ! 570: gotinfo[netbuffer->player&0x7f] = true; ! 571: } ! 572: ! 573: for (i=1 ; i<doomcom->numnodes ; i++) ! 574: if (!gotinfo[i]) ! 575: break; ! 576: } while (i < doomcom->numnodes); ! 577: } ! 578: } ! 579: ! 580: /* ! 581: =================== ! 582: = ! 583: = D_CheckNetGame ! 584: = ! 585: = Works out player numbers among the net participants ! 586: =================== ! 587: */ ! 588: ! 589: extern int viewangleoffset; ! 590: ! 591: void D_CheckNetGame (void) ! 592: { ! 593: int i; ! 594: ! 595: for (i=0 ; i<MAXNETNODES ; i++) ! 596: { ! 597: nodeingame[i] = false; ! 598: nettics[i] = 0; ! 599: remoteresend[i] = false; // set when local needs tics ! 600: resendto[i] = 0; // which tic to start sending ! 601: } ! 602: ! 603: // I_InitNetwork sets doomcom and netgame ! 604: I_InitNetwork (); ! 605: if (doomcom->id != DOOMCOM_ID) ! 606: I_Error ("Doomcom buffer invalid!"); ! 607: netbuffer = &doomcom->data; ! 608: consoleplayer = displayplayer = doomcom->consoleplayer; ! 609: if (netgame) ! 610: D_ArbitrateNetStart (); ! 611: //printf ("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", startskill, deathmatch, startmap, startepisode); ! 612: ! 613: // read values out of doomcom ! 614: ticdup = doomcom->ticdup; ! 615: ! 616: for (i=0 ; i<doomcom->numplayers ; i++) ! 617: playeringame[i] = true; ! 618: for (i=0 ; i<doomcom->numnodes ; i++) ! 619: nodeingame[i] = true; ! 620: ! 621: //printf ("player %i of %i (%i nodes)\n", consoleplayer+1, doomcom->numplayers, doomcom->numnodes); ! 622: ! 623: } ! 624: ! 625: /* ! 626: ================== ! 627: = ! 628: = D_QuitNetGame ! 629: = ! 630: = Called before quitting to leave a net game without hanging the ! 631: = other players ! 632: = ! 633: ================== ! 634: */ ! 635: ! 636: void D_QuitNetGame (void) ! 637: { ! 638: int i, j; ! 639: ! 640: if (debugfile) ! 641: fclose (debugfile); ! 642: ! 643: if (!netgame || !usergame || consoleplayer == -1) ! 644: return; ! 645: ! 646: // send a bunch of packets for security ! 647: netbuffer->player = consoleplayer; ! 648: if (doomcom->drone) ! 649: netbuffer->player |= PL_DRONE; ! 650: netbuffer->numtics = 0; ! 651: for (i=0 ; i<4 ; i++) ! 652: { ! 653: for (j=1 ; j<doomcom->numnodes ; j++) ! 654: if (nodeingame[j]) ! 655: HSendPacket (j, NCMD_EXIT); ! 656: I_WaitVBL (1); ! 657: } ! 658: } ! 659: ! 660: ! 661: ! 662: /* ! 663: =============== ! 664: = ! 665: = TryRunTics ! 666: = ! 667: =============== ! 668: */ ! 669: ! 670: int frametics[4], frameon; ! 671: int frameskip[4]; ! 672: int oldnettics; ! 673: extern boolean advancedemo; ! 674: ! 675: void TryRunTics (void) ! 676: { ! 677: int i; ! 678: int lowtic, nextlowest; ! 679: int entertic; ! 680: int static oldentertics; ! 681: int realtics, availabletics; ! 682: int counts; ! 683: int numplaying; ! 684: ! 685: // ! 686: // get real tics ! 687: // ! 688: entertic = I_GetTime (); ! 689: realtics = entertic - oldentertics; ! 690: oldentertics = entertic; ! 691: ! 692: // ! 693: // get available tics ! 694: // ! 695: NetUpdate (); ! 696: ! 697: lowtic = nextlowest = MAXINT; ! 698: numplaying = 0; ! 699: for (i=0 ; i<doomcom->numnodes ; i++) ! 700: if (nodeingame[i]) ! 701: { ! 702: numplaying++; ! 703: if (nettics[i] < lowtic) ! 704: { ! 705: nextlowest = lowtic; ! 706: lowtic = nettics[i]; ! 707: } ! 708: else if (nettics[i] < nextlowest) ! 709: nextlowest = nettics[i]; ! 710: } ! 711: availabletics = lowtic - gametic; ! 712: ! 713: ! 714: // ! 715: // decide how many tics to run ! 716: // ! 717: if (realtics < availabletics-1) ! 718: counts = realtics+1; ! 719: else if (realtics < availabletics) ! 720: counts = realtics; ! 721: else ! 722: counts = availabletics; ! 723: if (counts < 1) ! 724: counts = 1; ! 725: ! 726: frameon++; ! 727: ! 728: if (debugfile) ! 729: fprintf (debugfile,"=======real: %i avail: %i game: %i\n",realtics, availabletics,counts); ! 730: ! 731: //============================================================================= ! 732: // ! 733: // ideally nettics[0] should be 1 - 3 tics above lowtic ! 734: // if we are consistantly slower, speed up time ! 735: // drones should never hold up the other players ! 736: // ! 737: for (i=0 ; i<MAXPLAYERS ; i++) ! 738: if (playeringame[i]) ! 739: break; ! 740: if (consoleplayer == i) ! 741: { // the key player does not adapt ! 742: } ! 743: else ! 744: { ! 745: if (nettics[0] <= nettics[nodeforplayer[i]]) ! 746: { ! 747: gametime--; ! 748: // printf ("-"); ! 749: } ! 750: frameskip[frameon&3] = (oldnettics > nettics[nodeforplayer[i]]); ! 751: oldnettics = nettics[0]; ! 752: if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3]) ! 753: { ! 754: skiptics = 1; ! 755: // printf ("+"); ! 756: } ! 757: } ! 758: //============================================================================= ! 759: ! 760: // ! 761: // wait for new tics if needed ! 762: // ! 763: while (lowtic < gametic + counts) ! 764: { ! 765: ! 766: NetUpdate (); ! 767: lowtic = MAXINT; ! 768: ! 769: for (i=0 ; i<doomcom->numnodes ; i++) ! 770: if (nodeingame[i] && nettics[i] < lowtic) ! 771: lowtic = nettics[i]; ! 772: ! 773: if (lowtic < gametic) ! 774: I_Error ("TryRunTics: lowtic < gametic"); ! 775: ! 776: // don't stay in here forever -- give the menu a chance to work ! 777: if (I_GetTime () - entertic >= 20) ! 778: { ! 779: MN_Ticker (); ! 780: return; ! 781: } ! 782: } ! 783: ! 784: ! 785: // ! 786: // run the tics ! 787: // ! 788: while (counts--) ! 789: { ! 790: if (advancedemo) ! 791: D_DoAdvanceDemo (); ! 792: MN_Ticker (); ! 793: G_Ticker (); ! 794: NetUpdate (); // check for new console commands ! 795: gametic++; ! 796: } ! 797: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.