d_net.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "Precompiled.h"
  21. #include "globaldata.h"
  22. #include "m_menu.h"
  23. #include "i_system.h"
  24. #include "i_video.h"
  25. #include "i_net.h"
  26. #include "g_game.h"
  27. #include "doomdef.h"
  28. #include "doomstat.h"
  29. #include "doomlib.h"
  30. #include "Main.h"
  31. #include "d3xp/Game_local.h"
  32. void I_GetEvents( controller_t * );
  33. void D_ProcessEvents (void);
  34. void G_BuildTiccmd (ticcmd_t *cmd, idUserCmdMgr *, int newTics );
  35. void D_DoAdvanceDemo (void);
  36. extern bool globalNetworking;
  37. //
  38. // NETWORKING
  39. //
  40. // ::g->gametic is the tic about to (or currently being) run
  41. // ::g->maketic is the tick that hasn't had control made for it yet
  42. // ::g->nettics[] has the maketics for all ::g->players
  43. //
  44. // a ::g->gametic cannot be run until ::g->nettics[] > ::g->gametic for all ::g->players
  45. //
  46. #define NET_TIMEOUT 1 * TICRATE
  47. //
  48. //
  49. //
  50. int NetbufferSize (void)
  51. {
  52. int size = (int)&(((doomdata_t *)0)->cmds[::g->netbuffer->numtics]);
  53. return size;
  54. }
  55. //
  56. // Checksum
  57. //
  58. unsigned NetbufferChecksum (void)
  59. {
  60. unsigned c;
  61. int i,l;
  62. c = 0x1234567;
  63. if ( globalNetworking ) {
  64. l = (NetbufferSize () - (int)&(((doomdata_t *)0)->retransmitfrom))/4;
  65. for (i=0 ; i<l ; i++)
  66. c += ((unsigned *)&::g->netbuffer->retransmitfrom)[i] * (i+1);
  67. }
  68. return c & NCMD_CHECKSUM;
  69. }
  70. //
  71. //
  72. //
  73. int ExpandTics (int low)
  74. {
  75. int delta;
  76. delta = low - (::g->maketic&0xff);
  77. if (delta >= -64 && delta <= 64)
  78. return (::g->maketic&~0xff) + low;
  79. if (delta > 64)
  80. return (::g->maketic&~0xff) - 256 + low;
  81. if (delta < -64)
  82. return (::g->maketic&~0xff) + 256 + low;
  83. I_Error ("ExpandTics: strange value %i at ::g->maketic %i",low,::g->maketic);
  84. return 0;
  85. }
  86. //
  87. // HSendPacket
  88. //
  89. void
  90. HSendPacket
  91. (int node,
  92. int flags )
  93. {
  94. ::g->netbuffer->checksum = NetbufferChecksum () | flags;
  95. if (!node)
  96. {
  97. ::g->reboundstore = *::g->netbuffer;
  98. ::g->reboundpacket = true;
  99. return;
  100. }
  101. if (::g->demoplayback)
  102. return;
  103. if (!::g->netgame)
  104. I_Error ("Tried to transmit to another node");
  105. ::g->doomcom.command = CMD_SEND;
  106. ::g->doomcom.remotenode = node;
  107. ::g->doomcom.datalength = NetbufferSize ();
  108. if (::g->debugfile)
  109. {
  110. int i;
  111. int realretrans;
  112. if (::g->netbuffer->checksum & NCMD_RETRANSMIT)
  113. realretrans = ExpandTics (::g->netbuffer->retransmitfrom);
  114. else
  115. realretrans = -1;
  116. fprintf (::g->debugfile,"send (%i + %i, R %i) [%i] ",
  117. ExpandTics(::g->netbuffer->starttic),
  118. ::g->netbuffer->numtics, realretrans, ::g->doomcom.datalength);
  119. for (i=0 ; i < ::g->doomcom.datalength ; i++)
  120. fprintf (::g->debugfile,"%i ",((byte *)::g->netbuffer)[i]);
  121. fprintf (::g->debugfile,"\n");
  122. }
  123. I_NetCmd ();
  124. }
  125. //
  126. // HGetPacket
  127. // Returns false if no packet is waiting
  128. //
  129. qboolean HGetPacket (void)
  130. {
  131. if (::g->reboundpacket)
  132. {
  133. *::g->netbuffer = ::g->reboundstore;
  134. ::g->doomcom.remotenode = 0;
  135. ::g->reboundpacket = false;
  136. return true;
  137. }
  138. if (!::g->netgame)
  139. return false;
  140. if (::g->demoplayback)
  141. return false;
  142. ::g->doomcom.command = CMD_GET;
  143. I_NetCmd ();
  144. if (::g->doomcom.remotenode == -1)
  145. return false;
  146. if (::g->doomcom.datalength != NetbufferSize ())
  147. {
  148. if (::g->debugfile)
  149. fprintf (::g->debugfile,"bad packet length %i\n",::g->doomcom.datalength);
  150. return false;
  151. }
  152. // ALAN NETWORKING -- this fails a lot on 4 player split debug!!
  153. // TODO: Networking
  154. #ifdef ID_ENABLE_DOOM_CLASSIC_NETWORKING
  155. if ( !gameLocal->IsSplitscreen() && NetbufferChecksum() != (::g->netbuffer->checksum&NCMD_CHECKSUM) )
  156. {
  157. if (::g->debugfile) {
  158. fprintf (::g->debugfile,"bad packet checksum\n");
  159. }
  160. return false;
  161. }
  162. #endif
  163. if (::g->debugfile)
  164. {
  165. int realretrans;
  166. int i;
  167. if (::g->netbuffer->checksum & NCMD_SETUP)
  168. fprintf (::g->debugfile,"setup packet\n");
  169. else
  170. {
  171. if (::g->netbuffer->checksum & NCMD_RETRANSMIT)
  172. realretrans = ExpandTics (::g->netbuffer->retransmitfrom);
  173. else
  174. realretrans = -1;
  175. fprintf (::g->debugfile,"get %i = (%i + %i, R %i)[%i] ",
  176. ::g->doomcom.remotenode,
  177. ExpandTics(::g->netbuffer->starttic),
  178. ::g->netbuffer->numtics, realretrans, ::g->doomcom.datalength);
  179. for (i=0 ; i < ::g->doomcom.datalength ; i++)
  180. fprintf (::g->debugfile,"%i ",((byte *)::g->netbuffer)[i]);
  181. fprintf (::g->debugfile,"\n");
  182. }
  183. }
  184. return true;
  185. }
  186. //
  187. // GetPackets
  188. //
  189. void GetPackets (void)
  190. {
  191. int netconsole;
  192. int netnode;
  193. ticcmd_t *src, *dest;
  194. int realend;
  195. int realstart;
  196. while ( HGetPacket() )
  197. {
  198. if (::g->netbuffer->checksum & NCMD_SETUP)
  199. continue; // extra setup packet
  200. netconsole = ::g->netbuffer->player & ~PL_DRONE;
  201. netnode = ::g->doomcom.remotenode;
  202. // to save bytes, only the low byte of tic numbers are sent
  203. // Figure out what the rest of the bytes are
  204. realstart = ExpandTics (::g->netbuffer->starttic);
  205. realend = (realstart+::g->netbuffer->numtics);
  206. // check for exiting the game
  207. if (::g->netbuffer->checksum & NCMD_EXIT)
  208. {
  209. if (!::g->nodeingame[netnode])
  210. continue;
  211. ::g->nodeingame[netnode] = false;
  212. ::g->playeringame[netconsole] = false;
  213. strcpy (::g->exitmsg, "Player 1 left the game");
  214. ::g->exitmsg[7] += netconsole;
  215. ::g->players[::g->consoleplayer].message = ::g->exitmsg;
  216. if( ::g->demorecording ) {
  217. G_CheckDemoStatus();
  218. }
  219. continue;
  220. }
  221. // check for a remote game kill
  222. /*
  223. if (::g->netbuffer->checksum & NCMD_KILL)
  224. I_Error ("Killed by network driver");
  225. */
  226. ::g->nodeforplayer[netconsole] = netnode;
  227. // check for retransmit request
  228. if ( ::g->resendcount[netnode] <= 0
  229. && (::g->netbuffer->checksum & NCMD_RETRANSMIT) )
  230. {
  231. ::g->resendto[netnode] = ExpandTics(::g->netbuffer->retransmitfrom);
  232. if (::g->debugfile)
  233. fprintf (::g->debugfile,"retransmit from %i\n", ::g->resendto[netnode]);
  234. ::g->resendcount[netnode] = RESENDCOUNT;
  235. }
  236. else
  237. ::g->resendcount[netnode]--;
  238. // check for out of order / duplicated packet
  239. if (realend == ::g->nettics[netnode])
  240. continue;
  241. if (realend < ::g->nettics[netnode])
  242. {
  243. if (::g->debugfile)
  244. fprintf (::g->debugfile,
  245. "out of order packet (%i + %i)\n" ,
  246. realstart,::g->netbuffer->numtics);
  247. continue;
  248. }
  249. // check for a missed packet
  250. if (realstart > ::g->nettics[netnode])
  251. {
  252. // stop processing until the other system resends the missed tics
  253. if (::g->debugfile)
  254. fprintf (::g->debugfile,
  255. "missed tics from %i (%i - %i)\n",
  256. netnode, realstart, ::g->nettics[netnode]);
  257. ::g->remoteresend[netnode] = true;
  258. continue;
  259. }
  260. // update command store from the packet
  261. {
  262. int start;
  263. ::g->remoteresend[netnode] = false;
  264. start = ::g->nettics[netnode] - realstart;
  265. src = &::g->netbuffer->cmds[start];
  266. while (::g->nettics[netnode] < realend)
  267. {
  268. dest = &::g->netcmds[netconsole][::g->nettics[netnode]%BACKUPTICS];
  269. ::g->nettics[netnode]++;
  270. *dest = *src;
  271. src++;
  272. }
  273. }
  274. }
  275. }
  276. //
  277. // NetUpdate
  278. // Builds ticcmds for console player,
  279. // sends out a packet
  280. //
  281. void NetUpdate ( idUserCmdMgr * userCmdMgr )
  282. {
  283. int nowtime;
  284. int newtics;
  285. int i,j;
  286. int realstart;
  287. int gameticdiv;
  288. // check time
  289. nowtime = I_GetTime ()/::g->ticdup;
  290. newtics = nowtime - ::g->gametime;
  291. ::g->gametime = nowtime;
  292. if (newtics <= 0) // nothing new to update
  293. goto listen;
  294. if (::g->skiptics <= newtics)
  295. {
  296. newtics -= ::g->skiptics;
  297. ::g->skiptics = 0;
  298. }
  299. else
  300. {
  301. ::g->skiptics -= newtics;
  302. newtics = 0;
  303. }
  304. ::g->netbuffer->player = ::g->consoleplayer;
  305. // build new ticcmds for console player
  306. gameticdiv = ::g->gametic/::g->ticdup;
  307. for (i=0 ; i<newtics ; i++)
  308. {
  309. //I_GetEvents( ::g->I_StartTicCallback () );
  310. D_ProcessEvents ();
  311. if (::g->maketic - gameticdiv >= BACKUPTICS/2-1) {
  312. printf( "Out of room for ticcmds: maketic = %d, gameticdiv = %d\n", ::g->maketic, gameticdiv );
  313. break; // can't hold any more
  314. }
  315. //I_Printf ("mk:%i ",::g->maketic);
  316. // Grab the latest tech5 command
  317. G_BuildTiccmd (&::g->localcmds[::g->maketic%BACKUPTICS], userCmdMgr, newtics );
  318. ::g->maketic++;
  319. }
  320. if (::g->singletics)
  321. return; // singletic update is syncronous
  322. // send the packet to the other ::g->nodes
  323. for (i=0 ; i < ::g->doomcom.numnodes ; i++) {
  324. if (::g->nodeingame[i]) {
  325. ::g->netbuffer->starttic = realstart = ::g->resendto[i];
  326. ::g->netbuffer->numtics = ::g->maketic - realstart;
  327. if (::g->netbuffer->numtics > BACKUPTICS)
  328. I_Error ("NetUpdate: ::g->netbuffer->numtics > BACKUPTICS");
  329. ::g->resendto[i] = ::g->maketic - ::g->doomcom.extratics;
  330. for (j=0 ; j< ::g->netbuffer->numtics ; j++)
  331. ::g->netbuffer->cmds[j] =
  332. ::g->localcmds[(realstart+j)%BACKUPTICS];
  333. if (::g->remoteresend[i])
  334. {
  335. ::g->netbuffer->retransmitfrom = ::g->nettics[i];
  336. HSendPacket (i, NCMD_RETRANSMIT);
  337. }
  338. else
  339. {
  340. ::g->netbuffer->retransmitfrom = 0;
  341. HSendPacket (i, 0);
  342. }
  343. }
  344. }
  345. // listen for other packets
  346. listen:
  347. GetPackets ();
  348. }
  349. //
  350. // CheckAbort
  351. //
  352. void CheckAbort (void)
  353. {
  354. // DHM - Time starts at 0 tics when starting a multiplayer game, so we can
  355. // check for timeouts easily. If we're still waiting after N seconds, abort.
  356. if ( I_GetTime() > NET_TIMEOUT ) {
  357. // TOOD: Show error & leave net game.
  358. printf( "NET GAME TIMED OUT!\n" );
  359. //gameLocal->showFatalErrorMessage( XuiLookupStringTable(globalStrings,L"Timed out waiting for match start.") );
  360. D_QuitNetGame();
  361. session->QuitMatch();
  362. common->Dialog().AddDialog( GDM_OPPONENT_CONNECTION_LOST, DIALOG_ACCEPT, NULL, NULL, false );
  363. }
  364. }
  365. //
  366. // D_ArbitrateNetStart
  367. //
  368. bool D_ArbitrateNetStart (void)
  369. {
  370. int i;
  371. ::g->autostart = true;
  372. if (::g->doomcom.consoleplayer)
  373. {
  374. // listen for setup info from key player
  375. CheckAbort ();
  376. if (!HGetPacket ())
  377. return false;
  378. if (::g->netbuffer->checksum & NCMD_SETUP)
  379. {
  380. printf( "Received setup info\n" );
  381. if (::g->netbuffer->player != VERSION)
  382. I_Error ("Different DOOM versions cannot play a net game!");
  383. ::g->startskill = (skill_t)(::g->netbuffer->retransmitfrom & 15);
  384. ::g->deathmatch = (::g->netbuffer->retransmitfrom & 0xc0) >> 6;
  385. ::g->nomonsters = (::g->netbuffer->retransmitfrom & 0x20) > 0;
  386. ::g->respawnparm = (::g->netbuffer->retransmitfrom & 0x10) > 0;
  387. // VV original xbox doom :: don't do this.. it will be setup from the launcher
  388. //::g->startmap = ::g->netbuffer->starttic & 0x3f;
  389. //::g->startepisode = ::g->netbuffer->starttic >> 6;
  390. return true;
  391. }
  392. return false;
  393. }
  394. else
  395. {
  396. // key player, send the setup info
  397. CheckAbort ();
  398. for (i=0 ; i < ::g->doomcom.numnodes ; i++)
  399. {
  400. printf( "Sending setup info to node %d\n", i );
  401. ::g->netbuffer->retransmitfrom = ::g->startskill;
  402. if (::g->deathmatch)
  403. ::g->netbuffer->retransmitfrom |= (::g->deathmatch<<6);
  404. if (::g->nomonsters)
  405. ::g->netbuffer->retransmitfrom |= 0x20;
  406. if (::g->respawnparm)
  407. ::g->netbuffer->retransmitfrom |= 0x10;
  408. ::g->netbuffer->starttic = ::g->startepisode * 64 + ::g->startmap;
  409. ::g->netbuffer->player = VERSION;
  410. ::g->netbuffer->numtics = 0;
  411. HSendPacket (i, NCMD_SETUP);
  412. }
  413. while (HGetPacket ())
  414. {
  415. ::g->gotinfo[::g->netbuffer->player&0x7f] = true;
  416. }
  417. for (i=1 ; i < ::g->doomcom.numnodes ; i++) {
  418. if (!::g->gotinfo[i])
  419. break;
  420. }
  421. if (i >= ::g->doomcom.numnodes)
  422. return true;
  423. return false;
  424. }
  425. }
  426. //
  427. // D_CheckNetGame
  428. // Works out player numbers among the net participants
  429. //
  430. void D_CheckNetGame (void)
  431. {
  432. int i;
  433. for (i=0 ; i<MAXNETNODES ; i++)
  434. {
  435. ::g->nodeingame[i] = false;
  436. ::g->nettics[i] = 0;
  437. ::g->remoteresend[i] = false; // set when local needs tics
  438. ::g->resendto[i] = 0; // which tic to start sending
  439. }
  440. // I_InitNetwork sets ::g->doomcom and ::g->netgame
  441. I_InitNetwork ();
  442. #ifdef ID_ENABLE_DOOM_CLASSIC_NETWORKING
  443. if (::g->doomcom.id != DOOMCOM_ID)
  444. I_Error ("Doomcom buffer invalid!");
  445. #endif
  446. ::g->netbuffer = &::g->doomcom.data;
  447. ::g->consoleplayer = ::g->displayplayer = ::g->doomcom.consoleplayer;
  448. }
  449. bool D_PollNetworkStart()
  450. {
  451. int i;
  452. if (::g->netgame)
  453. {
  454. if (D_ArbitrateNetStart () == false)
  455. return false;
  456. }
  457. I_Printf ("startskill %i deathmatch: %i startmap: %i startepisode: %i\n",
  458. ::g->startskill, ::g->deathmatch, ::g->startmap, ::g->startepisode);
  459. // read values out of ::g->doomcom
  460. ::g->ticdup = ::g->doomcom.ticdup;
  461. ::g->maxsend = BACKUPTICS/(2*::g->ticdup)-1;
  462. if (::g->maxsend<1)
  463. ::g->maxsend = 1;
  464. for (i=0 ; i < ::g->doomcom.numplayers ; i++)
  465. ::g->playeringame[i] = true;
  466. for (i=0 ; i < ::g->doomcom.numnodes ; i++)
  467. ::g->nodeingame[i] = true;
  468. I_Printf ("player %i of %i (%i ::g->nodes)\n",
  469. ::g->consoleplayer+1, ::g->doomcom.numplayers, ::g->doomcom.numnodes);
  470. return true;
  471. }
  472. //
  473. // D_QuitNetGame
  474. // Called before quitting to leave a net game
  475. // without hanging the other ::g->players
  476. //
  477. void D_QuitNetGame (void)
  478. {
  479. int i;
  480. if ( (!::g->netgame && !::g->usergame) || ::g->consoleplayer == -1 || ::g->demoplayback || ::g->netbuffer == NULL )
  481. return;
  482. // send a quit packet to the other nodes
  483. ::g->netbuffer->player = ::g->consoleplayer;
  484. ::g->netbuffer->numtics = 0;
  485. for ( i=1; i < ::g->doomcom.numnodes; i++ ) {
  486. if ( ::g->nodeingame[i] ) {
  487. HSendPacket( i, NCMD_EXIT );
  488. }
  489. }
  490. DoomLib::SendNetwork();
  491. for (i=1 ; i<MAXNETNODES ; i++)
  492. {
  493. ::g->nodeingame[i] = false;
  494. ::g->nettics[i] = 0;
  495. ::g->remoteresend[i] = false; // set when local needs tics
  496. ::g->resendto[i] = 0; // which tic to start sending
  497. }
  498. //memset (&::g->doomcom, 0, sizeof(::g->doomcom) );
  499. // Reset singleplayer state
  500. ::g->doomcom.id = DOOMCOM_ID;
  501. ::g->doomcom.ticdup = 1;
  502. ::g->doomcom.extratics = 0;
  503. ::g->doomcom.numplayers = ::g->doomcom.numnodes = 1;
  504. ::g->doomcom.deathmatch = false;
  505. ::g->doomcom.consoleplayer = 0;
  506. ::g->netgame = false;
  507. ::g->netbuffer = &::g->doomcom.data;
  508. ::g->consoleplayer = ::g->displayplayer = ::g->doomcom.consoleplayer;
  509. ::g->ticdup = ::g->doomcom.ticdup;
  510. ::g->maxsend = BACKUPTICS/(2*::g->ticdup)-1;
  511. if (::g->maxsend<1)
  512. ::g->maxsend = 1;
  513. for (i=0 ; i < ::g->doomcom.numplayers ; i++)
  514. ::g->playeringame[i] = true;
  515. for (i=0 ; i < ::g->doomcom.numnodes ; i++)
  516. ::g->nodeingame[i] = true;
  517. }
  518. //
  519. // TryRunTics
  520. //
  521. bool TryRunTics ( idUserCmdMgr * userCmdMgr )
  522. {
  523. int i;
  524. int lowtic_node = -1;
  525. // get real tics
  526. ::g->trt_entertic = I_GetTime ()/::g->ticdup;
  527. ::g->trt_realtics = ::g->trt_entertic - ::g->oldtrt_entertics;
  528. ::g->oldtrt_entertics = ::g->trt_entertic;
  529. // get available tics
  530. NetUpdate ( userCmdMgr );
  531. ::g->trt_lowtic = MAXINT;
  532. ::g->trt_numplaying = 0;
  533. for (i=0 ; i < ::g->doomcom.numnodes ; i++) {
  534. if (::g->nodeingame[i]) {
  535. ::g->trt_numplaying++;
  536. if (::g->nettics[i] < ::g->trt_lowtic) {
  537. ::g->trt_lowtic = ::g->nettics[i];
  538. lowtic_node = i;
  539. }
  540. }
  541. }
  542. ::g->trt_availabletics = ::g->trt_lowtic - ::g->gametic/::g->ticdup;
  543. // decide how many tics to run
  544. if (::g->trt_realtics < ::g->trt_availabletics-1) {
  545. ::g->trt_counts = ::g->trt_realtics+1;
  546. } else if (::g->trt_realtics < ::g->trt_availabletics) {
  547. ::g->trt_counts = ::g->trt_realtics;
  548. } else {
  549. ::g->trt_counts = ::g->trt_availabletics;
  550. }
  551. if (::g->trt_counts < 1) {
  552. ::g->trt_counts = 1;
  553. }
  554. ::g->frameon++;
  555. if (::g->debugfile) {
  556. fprintf (::g->debugfile, "=======real: %i avail: %i game: %i\n", ::g->trt_realtics, ::g->trt_availabletics,::g->trt_counts);
  557. }
  558. if ( !::g->demoplayback )
  559. {
  560. // ideally ::g->nettics[0] should be 1 - 3 tics above ::g->trt_lowtic
  561. // if we are consistantly slower, speed up time
  562. for (i=0 ; i<MAXPLAYERS ; i++) {
  563. if (::g->playeringame[i]) {
  564. break;
  565. }
  566. }
  567. if (::g->consoleplayer == i) {
  568. // the key player does not adapt
  569. }
  570. else {
  571. if (::g->nettics[0] <= ::g->nettics[::g->nodeforplayer[i]]) {
  572. ::g->gametime--;
  573. //OutputDebugString("-");
  574. }
  575. ::g->frameskip[::g->frameon&3] = (::g->oldnettics > ::g->nettics[::g->nodeforplayer[i]]);
  576. ::g->oldnettics = ::g->nettics[0];
  577. if (::g->frameskip[0] && ::g->frameskip[1] && ::g->frameskip[2] && ::g->frameskip[3]) {
  578. ::g->skiptics = 1;
  579. //OutputDebugString("+");
  580. }
  581. }
  582. }
  583. // wait for new tics if needed
  584. if (::g->trt_lowtic < ::g->gametic/::g->ticdup + ::g->trt_counts)
  585. {
  586. int lagtime = 0;
  587. if (::g->trt_lowtic < ::g->gametic/::g->ticdup) {
  588. I_Error ("TryRunTics: ::g->trt_lowtic < gametic");
  589. }
  590. if ( ::g->lastnettic == 0 ) {
  591. ::g->lastnettic = ::g->trt_entertic;
  592. }
  593. lagtime = ::g->trt_entertic - ::g->lastnettic;
  594. // Detect if a client has stopped sending updates, remove them from the game after 5 secs.
  595. if ( common->IsMultiplayer() && (!::g->demoplayback && ::g->netgame) && lagtime >= TICRATE ) {
  596. if ( lagtime > NET_TIMEOUT ) {
  597. if ( lowtic_node == ::g->nodeforplayer[::g->consoleplayer] ) {
  598. #ifdef ID_ENABLE_DOOM_CLASSIC_NETWORKING
  599. #ifndef __PS3__
  600. gameLocal->showFatalErrorMessage( XuiLookupStringTable(globalStrings,L"You have been disconnected from the match.") );
  601. gameLocal->Interface.QuitCurrentGame();
  602. #endif
  603. #endif
  604. } else {
  605. if (::g->nodeingame[lowtic_node]) {
  606. int i, consoleNum = lowtic_node;
  607. for ( i=0; i < ::g->doomcom.numnodes; i++ ) {
  608. if ( ::g->nodeforplayer[i] == lowtic_node ) {
  609. consoleNum = i;
  610. break;
  611. }
  612. }
  613. ::g->nodeingame[lowtic_node] = false;
  614. ::g->playeringame[consoleNum] = false;
  615. strcpy (::g->exitmsg, "Player 1 left the game");
  616. ::g->exitmsg[7] += consoleNum;
  617. ::g->players[::g->consoleplayer].message = ::g->exitmsg;
  618. // Stop a demo record now, as playback doesn't support losing players
  619. G_CheckDemoStatus();
  620. }
  621. }
  622. }
  623. }
  624. return false;
  625. }
  626. ::g->lastnettic = 0;
  627. // run the count * ::g->ticdup dics
  628. while (::g->trt_counts--)
  629. {
  630. for (i=0 ; i < ::g->ticdup ; i++)
  631. {
  632. if (::g->gametic/::g->ticdup > ::g->trt_lowtic) {
  633. I_Error ("gametic(%d) greater than trt_lowtic(%d), trt_counts(%d)", ::g->gametic, ::g->trt_lowtic, ::g->trt_counts );
  634. return false;
  635. }
  636. if (::g->advancedemo) {
  637. D_DoAdvanceDemo ();
  638. }
  639. M_Ticker ();
  640. G_Ticker ();
  641. ::g->gametic++;
  642. // modify command for duplicated tics
  643. if (i != ::g->ticdup-1)
  644. {
  645. ticcmd_t *cmd;
  646. int buf;
  647. int j;
  648. buf = (::g->gametic/::g->ticdup)%BACKUPTICS;
  649. for (j=0 ; j<MAXPLAYERS ; j++)
  650. {
  651. cmd = &::g->netcmds[j][buf];
  652. if (cmd->buttons & BT_SPECIAL)
  653. cmd->buttons = 0;
  654. }
  655. }
  656. }
  657. NetUpdate ( userCmdMgr ); // check for new console commands
  658. }
  659. return true;
  660. }