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