summaryrefslogtreecommitdiff
path: root/src/heretic/d_net.c
diff options
context:
space:
mode:
authorSimon Howard2008-09-05 00:02:14 +0000
committerSimon Howard2008-09-05 00:02:14 +0000
commitc7ddc423f67236a99956960cf9fe89abf077839b (patch)
tree61322034e9d75f1c1a409d1e14ca21ee5c6025c2 /src/heretic/d_net.c
parent0774dce204c2c01622c59819e2a29590a1b50e46 (diff)
downloadchocolate-doom-c7ddc423f67236a99956960cf9fe89abf077839b.tar.gz
chocolate-doom-c7ddc423f67236a99956960cf9fe89abf077839b.tar.bz2
chocolate-doom-c7ddc423f67236a99956960cf9fe89abf077839b.zip
Reformat (beautify) Raven sources and add GPL headers.
Subversion-branch: /branches/raven-branch Subversion-revision: 1197
Diffstat (limited to 'src/heretic/d_net.c')
-rw-r--r--src/heretic/d_net.c1592
1 files changed, 810 insertions, 782 deletions
diff --git a/src/heretic/d_net.c b/src/heretic/d_net.c
index a11ac16f..261ed2b2 100644
--- a/src/heretic/d_net.c
+++ b/src/heretic/d_net.c
@@ -1,784 +1,812 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 1993-2008 Raven Software
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
-// d_net.c
+// d_net.c
// This version has the fixed ticdup code
-
-#include "DoomDef.h"
-
-#define NCMD_EXIT 0x80000000
-#define NCMD_RETRANSMIT 0x40000000
-#define NCMD_SETUP 0x20000000
-#define NCMD_KILL 0x10000000 // kill game
-#define NCMD_CHECKSUM 0x0fffffff
-
-
-doomcom_t *doomcom;
-doomdata_t *netbuffer; // points inside doomcom
-
-
-/*
-==============================================================================
-
- NETWORKING
-
-gametic is the tic about to (or currently being) run
-maketic is the tick that hasn't had control made for it yet
-nettics[] has the maketics for all players
-
-a gametic cannot be run until nettics[] > gametic for all players
-
-==============================================================================
-*/
-
-#define RESENDCOUNT 10
-#define PL_DRONE 0x80 // bit flag in doomdata->player
-
-ticcmd_t localcmds[BACKUPTICS];
-
-ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
-int nettics[MAXNETNODES];
-boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
-boolean remoteresend[MAXNETNODES]; // set when local needs tics
-int resendto[MAXNETNODES]; // set when remote needs tics
-int resendcount[MAXNETNODES];
-
-int nodeforplayer[MAXPLAYERS];
-
-int maketic;
-int lastnettic, skiptics;
-int ticdup;
-int maxsend; // BACKUPTICS/(2*ticdup)-1
-
-void D_ProcessEvents (void);
-void G_BuildTiccmd (ticcmd_t *cmd);
-void D_DoAdvanceDemo (void);
-
-boolean reboundpacket;
-doomdata_t reboundstore;
-
-
-int NetbufferSize (void)
-{
- return (int)&(((doomdata_t *)0)->cmds[netbuffer->numtics]);
-}
-
-unsigned NetbufferChecksum (void)
-{
- unsigned c;
- int i,l;
-
- c = 0x1234567;
-
-#if defined(NeXT) || defined(NORMALUNIX)
- return 0; // byte order problems
-#endif
-
- l = (NetbufferSize () - (int)&(((doomdata_t *)0)->retransmitfrom))/4;
- for (i=0 ; i<l ; i++)
- c += ((unsigned *)&netbuffer->retransmitfrom)[i] * (i+1);
-
- return c & NCMD_CHECKSUM;
-}
-
-int ExpandTics (int low)
-{
- int delta;
-
- delta = low - (maketic&0xff);
-
- if (delta >= -64 && delta <= 64)
- return (maketic&~0xff) + low;
- if (delta > 64)
- return (maketic&~0xff) - 256 + low;
- if (delta < -64)
- return (maketic&~0xff) + 256 + low;
-
- I_Error ("ExpandTics: strange value %i at maketic %i",low,maketic);
- return 0;
-}
-
-
-//============================================================================
-
-
-/*
-==============
-=
-= HSendPacket
-=
-==============
-*/
-
-void HSendPacket (int node, int flags)
-{
- netbuffer->checksum = NetbufferChecksum () | flags;
-
- if (!node)
- {
- reboundstore = *netbuffer;
- reboundpacket = true;
- return;
- }
-
- if (demoplayback)
- return;
-
- if (!netgame)
- I_Error ("Tried to transmit to another node");
-
- doomcom->command = CMD_SEND;
- doomcom->remotenode = node;
- doomcom->datalength = NetbufferSize ();
-
-if (debugfile)
-{
- int i;
- int realretrans;
- if (netbuffer->checksum & NCMD_RETRANSMIT)
- realretrans = ExpandTics (netbuffer->retransmitfrom);
- else
- realretrans = -1;
- fprintf (debugfile,"send (%i + %i, R %i) [%i] "
- ,ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength);
- for (i=0 ; i<doomcom->datalength ; i++)
- fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
- fprintf (debugfile,"\n");
-}
-
- I_NetCmd ();
-}
-
-/*
-==============
-=
-= HGetPacket
-=
-= Returns false if no packet is waiting
-=
-==============
-*/
-
-boolean HGetPacket (void)
-{
- if (reboundpacket)
- {
- *netbuffer = reboundstore;
- doomcom->remotenode = 0;
- reboundpacket = false;
- return true;
- }
-
- if (!netgame)
- return false;
- if (demoplayback)
- return false;
-
- doomcom->command = CMD_GET;
- I_NetCmd ();
- if (doomcom->remotenode == -1)
- return false;
-
- if (doomcom->datalength != NetbufferSize ())
- {
- if (debugfile)
- fprintf (debugfile,"bad packet length %i\n",doomcom->datalength);
- return false;
- }
-
- if (NetbufferChecksum () != (netbuffer->checksum&NCMD_CHECKSUM) )
- {
- if (debugfile)
- fprintf (debugfile,"bad packet checksum\n");
- return false;
- }
-
-if (debugfile)
-{
- int realretrans;
- int i;
-
- if (netbuffer->checksum & NCMD_SETUP)
- fprintf (debugfile,"setup packet\n");
- else
- {
- if (netbuffer->checksum & NCMD_RETRANSMIT)
- realretrans = ExpandTics (netbuffer->retransmitfrom);
- else
- realretrans = -1;
- fprintf (debugfile,"get %i = (%i + %i, R %i)[%i] ",doomcom->remotenode,
- ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength);
- for (i=0 ; i<doomcom->datalength ; i++)
- fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
- fprintf (debugfile,"\n");
- }
-}
- return true;
-}
-
-
-/*
-===================
-=
-= GetPackets
-=
-===================
-*/
-
-char exitmsg[80];
-
-void GetPackets (void)
-{
- int netconsole;
- int netnode;
- ticcmd_t *src, *dest;
- int realend;
- int realstart;
-
- while (HGetPacket ())
- {
- if (netbuffer->checksum & NCMD_SETUP)
- continue; // extra setup packet
-
- netconsole = netbuffer->player & ~PL_DRONE;
- netnode = doomcom->remotenode;
- //
- // to save bytes, only the low byte of tic numbers are sent
- // Figure out what the rest of the bytes are
- //
- realstart = ExpandTics (netbuffer->starttic);
- realend = (realstart+netbuffer->numtics);
-
- //
- // check for exiting the game
- //
- if (netbuffer->checksum & NCMD_EXIT)
- {
- if (!nodeingame[netnode])
- continue;
- nodeingame[netnode] = false;
- playeringame[netconsole] = false;
- strcpy (exitmsg, "PLAYER 1 LEFT THE GAME");
- exitmsg[7] += netconsole;
- players[consoleplayer].message = exitmsg;
-// if (demorecording)
-// G_CheckDemoStatus ();
- continue;
- }
-
- //
- // check for a remote game kill
- //
- if (netbuffer->checksum & NCMD_KILL)
- I_Error ("Killed by network driver");
-
- nodeforplayer[netconsole] = netnode;
-
- //
- // check for retransmit request
- //
- if ( resendcount[netnode] <= 0
- && (netbuffer->checksum & NCMD_RETRANSMIT) )
- {
- resendto[netnode] = ExpandTics(netbuffer->retransmitfrom);
-if (debugfile)
-fprintf (debugfile,"retransmit from %i\n", resendto[netnode]);
- resendcount[netnode] = RESENDCOUNT;
- }
- else
- resendcount[netnode]--;
-
- //
- // check for out of order / duplicated packet
- //
- if (realend == nettics[netnode])
- continue;
-
- if (realend < nettics[netnode])
- {
-if (debugfile)
-fprintf (debugfile,"out of order packet (%i + %i)\n" ,realstart,netbuffer->numtics);
- continue;
- }
-
- //
- // check for a missed packet
- //
- if (realstart > nettics[netnode])
- {
- // stop processing until the other system resends the missed tics
-if (debugfile)
-fprintf (debugfile,"missed tics from %i (%i - %i)\n", netnode, realstart, nettics[netnode]);
- remoteresend[netnode] = true;
- continue;
- }
-
-//
-// update command store from the packet
-//
-{
- int start;
-
- remoteresend[netnode] = false;
-
- start = nettics[netnode] - realstart;
- src = &netbuffer->cmds[start];
-
- while (nettics[netnode] < realend)
- {
- dest = &netcmds[netconsole][nettics[netnode]%BACKUPTICS];
- nettics[netnode]++;
- *dest = *src;
- src++;
- }
- }
-}
-
-}
-
-/*
-=============
-=
-= NetUpdate
-=
-= Builds ticcmds for console player
-= sends out a packet
-=============
-*/
-
-int gametime;
-
-void NetUpdate (void)
-{
- int nowtime;
- int newtics;
- int i,j;
- int realstart;
- int gameticdiv;
-
-//
-// check time
-//
- nowtime = I_GetTime ()/ticdup;
- newtics = nowtime - gametime;
- gametime = nowtime;
-
- if (newtics <= 0) // nothing new to update
- goto listen;
-
- if (skiptics <= newtics)
- {
- newtics -= skiptics;
- skiptics = 0;
- }
- else
- {
- skiptics -= newtics;
- newtics = 0;
- }
-
-
- netbuffer->player = consoleplayer;
-
-//
-// build new ticcmds for console player
-//
- gameticdiv = gametic/ticdup;
- for (i=0 ; i<newtics ; i++)
- {
- I_StartTic ();
- D_ProcessEvents ();
- if (maketic - gameticdiv >= BACKUPTICS/2-1)
- break; // can't hold any more
-//printf ("mk:%i ",maketic);
- G_BuildTiccmd (&localcmds[maketic%BACKUPTICS]);
- maketic++;
- }
-
-
- if (singletics)
- return; // singletic update is syncronous
-
-//
-// send the packet to the other nodes
-//
- for (i=0 ; i<doomcom->numnodes ; i++)
- if (nodeingame[i])
- {
- netbuffer->starttic = realstart = resendto[i];
- netbuffer->numtics = maketic - realstart;
- if (netbuffer->numtics > BACKUPTICS)
- I_Error ("NetUpdate: netbuffer->numtics > BACKUPTICS");
-
- resendto[i] = maketic - doomcom->extratics;
-
- for (j=0 ; j< netbuffer->numtics ; j++)
- netbuffer->cmds[j] =
- localcmds[(realstart+j)%BACKUPTICS];
-
- if (remoteresend[i])
- {
- netbuffer->retransmitfrom = nettics[i];
- HSendPacket (i, NCMD_RETRANSMIT);
- }
- else
- {
- netbuffer->retransmitfrom = 0;
- HSendPacket (i, 0);
- }
- }
-
-//
-// listen for other packets
-//
-listen:
-
- GetPackets ();
-}
-
-
-/*
-=====================
-=
-= CheckAbort
-=
-=====================
-*/
-
-void CheckAbort (void)
-{
- event_t *ev;
- int stoptic;
-
- stoptic = I_GetTime () + 2;
- while (I_GetTime() < stoptic)
- I_StartTic ();
-
- I_StartTic ();
- for ( ; eventtail != eventhead
- ; eventtail = (++eventtail)&(MAXEVENTS-1) )
- {
- ev = &events[eventtail];
- if (ev->type == ev_keydown && ev->data1 == KEY_ESCAPE)
- I_Error ("Network game synchronization aborted.");
- }
-}
-
-/*
-=====================
-=
-= D_ArbitrateNetStart
-=
-=====================
-*/
-
-void D_ArbitrateNetStart (void)
-{
- int i;
- boolean gotinfo[MAXNETNODES];
-
- autostart = true;
- memset (gotinfo,0,sizeof(gotinfo));
-
- if (doomcom->consoleplayer)
- { // listen for setup info from key player
-// mprintf ("listening for network start info...\n");
- while (1)
- {
- CheckAbort ();
- if (!HGetPacket ())
- continue;
- if (netbuffer->checksum & NCMD_SETUP)
- {
- if (netbuffer->player != VERSION)
- I_Error ("Different DOOM versions cannot play a net game!");
- startskill = netbuffer->retransmitfrom & 15;
- deathmatch = (netbuffer->retransmitfrom & 0xc0) >> 6;
- nomonsters = (netbuffer->retransmitfrom & 0x20) > 0;
- respawnparm = (netbuffer->retransmitfrom & 0x10) > 0;
- //startmap = netbuffer->starttic & 0x3f;
- //startepisode = netbuffer->starttic >> 6;
- startmap = netbuffer->starttic&15;
- startepisode = netbuffer->starttic>>4;
- return;
- }
- }
- }
- else
- { // key player, send the setup info
-// mprintf ("sending network start info...\n");
- do
- {
- CheckAbort ();
- for (i=0 ; i<doomcom->numnodes ; i++)
- {
- netbuffer->retransmitfrom = startskill;
- if (deathmatch)
- netbuffer->retransmitfrom |= (deathmatch<<6);
- if (nomonsters)
- netbuffer->retransmitfrom |= 0x20;
- if (respawnparm)
- netbuffer->retransmitfrom |= 0x10;
- //netbuffer->starttic = startepisode * 64 + startmap;
- netbuffer->starttic = (startepisode<<4)+startmap;
- netbuffer->player = VERSION;
- netbuffer->numtics = 0;
- HSendPacket (i, NCMD_SETUP);
- }
-
-#if 1
- for(i = 10 ; i && HGetPacket(); --i)
- {
- if((netbuffer->player&0x7f) < MAXNETNODES)
- gotinfo[netbuffer->player&0x7f] = true;
- }
-#else
- while (HGetPacket ())
- {
- gotinfo[netbuffer->player&0x7f] = true;
- }
-#endif
-
- for (i=1 ; i<doomcom->numnodes ; i++)
- if (!gotinfo[i])
- break;
- } while (i < doomcom->numnodes);
- }
-}
-
-/*
-===================
-=
-= D_CheckNetGame
-=
-= Works out player numbers among the net participants
-===================
-*/
-
-extern int viewangleoffset;
-
-void D_CheckNetGame (void)
-{
- int i;
-
- for (i=0 ; i<MAXNETNODES ; i++)
- {
- nodeingame[i] = false;
- nettics[i] = 0;
- remoteresend[i] = false; // set when local needs tics
- resendto[i] = 0; // which tic to start sending
- }
-
-// I_InitNetwork sets doomcom and netgame
- I_InitNetwork ();
- if (doomcom->id != DOOMCOM_ID)
- I_Error ("Doomcom buffer invalid!");
- netbuffer = &doomcom->data;
- consoleplayer = displayplayer = doomcom->consoleplayer;
- if (netgame)
- D_ArbitrateNetStart ();
-//printf ("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", startskill, deathmatch, startmap, startepisode);
-
-// read values out of doomcom
- ticdup = doomcom->ticdup;
- maxsend = BACKUPTICS/(2*ticdup)-1;
- if (maxsend<1)
- maxsend = 1;
-
- for (i=0 ; i<doomcom->numplayers ; i++)
- playeringame[i] = true;
- for (i=0 ; i<doomcom->numnodes ; i++)
- nodeingame[i] = true;
-
-//printf ("player %i of %i (%i nodes)\n", consoleplayer+1, doomcom->numplayers, doomcom->numnodes);
-
-}
-
-/*
-==================
-=
-= D_QuitNetGame
-=
-= Called before quitting to leave a net game without hanging the
-= other players
-=
-==================
-*/
-
-void D_QuitNetGame (void)
-{
- int i, j;
-
- if (debugfile)
- fclose (debugfile);
-
- if (!netgame || !usergame || consoleplayer == -1 || demoplayback)
- return;
-
-// send a bunch of packets for security
- netbuffer->player = consoleplayer;
- netbuffer->numtics = 0;
- for (i=0 ; i<4 ; i++)
- {
- for (j=1 ; j<doomcom->numnodes ; j++)
- if (nodeingame[j])
- HSendPacket (j, NCMD_EXIT);
- I_WaitVBL (1);
- }
-}
-
-
-
-/*
-===============
-=
-= TryRunTics
-=
-===============
-*/
-
-int frametics[4], frameon;
-int frameskip[4];
-int oldnettics;
-extern boolean advancedemo;
-
-void TryRunTics (void)
-{
- int i;
- int lowtic;
- int entertic;
- static int oldentertics;
- int realtics, availabletics;
- int counts;
- int numplaying;
-
-//
-// get real tics
-//
- entertic = I_GetTime ()/ticdup;
- realtics = entertic - oldentertics;
- oldentertics = entertic;
-
-//
-// get available tics
-//
- NetUpdate ();
-
- lowtic = MAXINT;
- numplaying = 0;
- for (i=0 ; i<doomcom->numnodes ; i++)
- if (nodeingame[i])
- {
- numplaying++;
- if (nettics[i] < lowtic)
- lowtic = nettics[i];
- }
- availabletics = lowtic - gametic/ticdup;
-
-
-//
-// decide how many tics to run
-//
- if (realtics < availabletics-1)
- counts = realtics+1;
- else if (realtics < availabletics)
- counts = realtics;
- else
- counts = availabletics;
- if (counts < 1)
- counts = 1;
-
- frameon++;
-
-if (debugfile)
- fprintf (debugfile,"=======real: %i avail: %i game: %i\n",realtics, availabletics,counts);
-
- if (!demoplayback)
- {
- //=============================================================================
- //
- // ideally nettics[0] should be 1 - 3 tics above lowtic
- // if we are consistantly slower, speed up time
- //
- for (i=0 ; i<MAXPLAYERS ; i++)
- if (playeringame[i])
- break;
- if (consoleplayer == i)
- { // the key player does not adapt
- }
- else
- {
- if (nettics[0] <= nettics[nodeforplayer[i]])
- {
- gametime--;
- // printf ("-");
- }
- frameskip[frameon&3] = (oldnettics > nettics[nodeforplayer[i]]);
- oldnettics = nettics[0];
- if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
- {
- skiptics = 1;
- // printf ("+");
- }
- }
- //=============================================================================
- } // demoplayback
-
- //
- // wait for new tics if needed
- //
- while (lowtic < gametic/ticdup + counts)
- {
-
- NetUpdate ();
- lowtic = MAXINT;
-
- for (i=0 ; i<doomcom->numnodes ; i++)
- if (nodeingame[i] && nettics[i] < lowtic)
- lowtic = nettics[i];
-
- if (lowtic < gametic/ticdup)
- I_Error ("TryRunTics: lowtic < gametic");
-
- // don't stay in here forever -- give the menu a chance to work
- if (I_GetTime ()/ticdup - entertic >= 20)
- {
- MN_Ticker ();
- return;
- }
- }
-
-//
-// run the count * ticdup dics
-//
- while (counts--)
- {
- for (i=0 ; i<ticdup ; i++)
- {
- if (gametic/ticdup > lowtic)
- I_Error ("gametic>lowtic");
- if (advancedemo)
- D_DoAdvanceDemo ();
- MN_Ticker ();
- G_Ticker ();
- gametic++;
- //
- // modify command for duplicated tics
- //
- if (i != ticdup-1)
- {
- ticcmd_t *cmd;
- int buf;
- int j;
-
- buf = (gametic/ticdup)%BACKUPTICS;
- for (j=0 ; j<MAXPLAYERS ; j++)
- {
- cmd = &netcmds[j][buf];
- cmd->chatchar = 0;
- if (cmd->buttons & BT_SPECIAL)
- cmd->buttons = 0;
- }
- }
- }
- NetUpdate (); // check for new console commands
- }
-}
+
+#include "DoomDef.h"
+
+#define NCMD_EXIT 0x80000000
+#define NCMD_RETRANSMIT 0x40000000
+#define NCMD_SETUP 0x20000000
+#define NCMD_KILL 0x10000000 // kill game
+#define NCMD_CHECKSUM 0x0fffffff
+
+
+doomcom_t *doomcom;
+doomdata_t *netbuffer; // points inside doomcom
+
+
+/*
+==============================================================================
+
+ NETWORKING
+
+gametic is the tic about to (or currently being) run
+maketic is the tick that hasn't had control made for it yet
+nettics[] has the maketics for all players
+
+a gametic cannot be run until nettics[] > gametic for all players
+
+==============================================================================
+*/
+
+#define RESENDCOUNT 10
+#define PL_DRONE 0x80 // bit flag in doomdata->player
+
+ticcmd_t localcmds[BACKUPTICS];
+
+ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
+int nettics[MAXNETNODES];
+boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
+boolean remoteresend[MAXNETNODES]; // set when local needs tics
+int resendto[MAXNETNODES]; // set when remote needs tics
+int resendcount[MAXNETNODES];
+
+int nodeforplayer[MAXPLAYERS];
+
+int maketic;
+int lastnettic, skiptics;
+int ticdup;
+int maxsend; // BACKUPTICS/(2*ticdup)-1
+
+void D_ProcessEvents(void);
+void G_BuildTiccmd(ticcmd_t * cmd);
+void D_DoAdvanceDemo(void);
+
+boolean reboundpacket;
+doomdata_t reboundstore;
+
+
+int NetbufferSize(void)
+{
+ return (int) &(((doomdata_t *) 0)->cmds[netbuffer->numtics]);
+}
+
+unsigned NetbufferChecksum(void)
+{
+ unsigned c;
+ int i, l;
+
+ c = 0x1234567;
+
+#if defined(NeXT) || defined(NORMALUNIX)
+ return 0; // byte order problems
+#endif
+
+ l = (NetbufferSize() - (int) &(((doomdata_t *) 0)->retransmitfrom)) / 4;
+ for (i = 0; i < l; i++)
+ c += ((unsigned *) &netbuffer->retransmitfrom)[i] * (i + 1);
+
+ return c & NCMD_CHECKSUM;
+}
+
+int ExpandTics(int low)
+{
+ int delta;
+
+ delta = low - (maketic & 0xff);
+
+ if (delta >= -64 && delta <= 64)
+ return (maketic & ~0xff) + low;
+ if (delta > 64)
+ return (maketic & ~0xff) - 256 + low;
+ if (delta < -64)
+ return (maketic & ~0xff) + 256 + low;
+
+ I_Error("ExpandTics: strange value %i at maketic %i", low, maketic);
+ return 0;
+}
+
+
+//============================================================================
+
+
+/*
+==============
+=
+= HSendPacket
+=
+==============
+*/
+
+void HSendPacket(int node, int flags)
+{
+ netbuffer->checksum = NetbufferChecksum() | flags;
+
+ if (!node)
+ {
+ reboundstore = *netbuffer;
+ reboundpacket = true;
+ return;
+ }
+
+ if (demoplayback)
+ return;
+
+ if (!netgame)
+ I_Error("Tried to transmit to another node");
+
+ doomcom->command = CMD_SEND;
+ doomcom->remotenode = node;
+ doomcom->datalength = NetbufferSize();
+
+ if (debugfile)
+ {
+ int i;
+ int realretrans;
+ if (netbuffer->checksum & NCMD_RETRANSMIT)
+ realretrans = ExpandTics(netbuffer->retransmitfrom);
+ else
+ realretrans = -1;
+ fprintf(debugfile, "send (%i + %i, R %i) [%i] ",
+ ExpandTics(netbuffer->starttic), netbuffer->numtics,
+ realretrans, doomcom->datalength);
+ for (i = 0; i < doomcom->datalength; i++)
+ fprintf(debugfile, "%i ", ((byte *) netbuffer)[i]);
+ fprintf(debugfile, "\n");
+ }
+
+ I_NetCmd();
+}
+
+/*
+==============
+=
+= HGetPacket
+=
+= Returns false if no packet is waiting
+=
+==============
+*/
+
+boolean HGetPacket(void)
+{
+ if (reboundpacket)
+ {
+ *netbuffer = reboundstore;
+ doomcom->remotenode = 0;
+ reboundpacket = false;
+ return true;
+ }
+
+ if (!netgame)
+ return false;
+ if (demoplayback)
+ return false;
+
+ doomcom->command = CMD_GET;
+ I_NetCmd();
+ if (doomcom->remotenode == -1)
+ return false;
+
+ if (doomcom->datalength != NetbufferSize())
+ {
+ if (debugfile)
+ fprintf(debugfile, "bad packet length %i\n", doomcom->datalength);
+ return false;
+ }
+
+ if (NetbufferChecksum() != (netbuffer->checksum & NCMD_CHECKSUM))
+ {
+ if (debugfile)
+ fprintf(debugfile, "bad packet checksum\n");
+ return false;
+ }
+
+ if (debugfile)
+ {
+ int realretrans;
+ int i;
+
+ if (netbuffer->checksum & NCMD_SETUP)
+ fprintf(debugfile, "setup packet\n");
+ else
+ {
+ if (netbuffer->checksum & NCMD_RETRANSMIT)
+ realretrans = ExpandTics(netbuffer->retransmitfrom);
+ else
+ realretrans = -1;
+ fprintf(debugfile, "get %i = (%i + %i, R %i)[%i] ",
+ doomcom->remotenode, ExpandTics(netbuffer->starttic),
+ netbuffer->numtics, realretrans, doomcom->datalength);
+ for (i = 0; i < doomcom->datalength; i++)
+ fprintf(debugfile, "%i ", ((byte *) netbuffer)[i]);
+ fprintf(debugfile, "\n");
+ }
+ }
+ return true;
+}
+
+
+/*
+===================
+=
+= GetPackets
+=
+===================
+*/
+
+char exitmsg[80];
+
+void GetPackets(void)
+{
+ int netconsole;
+ int netnode;
+ ticcmd_t *src, *dest;
+ int realend;
+ int realstart;
+
+ while (HGetPacket())
+ {
+ if (netbuffer->checksum & NCMD_SETUP)
+ continue; // extra setup packet
+
+ netconsole = netbuffer->player & ~PL_DRONE;
+ netnode = doomcom->remotenode;
+ //
+ // to save bytes, only the low byte of tic numbers are sent
+ // Figure out what the rest of the bytes are
+ //
+ realstart = ExpandTics(netbuffer->starttic);
+ realend = (realstart + netbuffer->numtics);
+
+ //
+ // check for exiting the game
+ //
+ if (netbuffer->checksum & NCMD_EXIT)
+ {
+ if (!nodeingame[netnode])
+ continue;
+ nodeingame[netnode] = false;
+ playeringame[netconsole] = false;
+ strcpy(exitmsg, "PLAYER 1 LEFT THE GAME");
+ exitmsg[7] += netconsole;
+ players[consoleplayer].message = exitmsg;
+// if (demorecording)
+// G_CheckDemoStatus ();
+ continue;
+ }
+
+ //
+ // check for a remote game kill
+ //
+ if (netbuffer->checksum & NCMD_KILL)
+ I_Error("Killed by network driver");
+
+ nodeforplayer[netconsole] = netnode;
+
+ //
+ // check for retransmit request
+ //
+ if (resendcount[netnode] <= 0
+ && (netbuffer->checksum & NCMD_RETRANSMIT))
+ {
+ resendto[netnode] = ExpandTics(netbuffer->retransmitfrom);
+ if (debugfile)
+ fprintf(debugfile, "retransmit from %i\n", resendto[netnode]);
+ resendcount[netnode] = RESENDCOUNT;
+ }
+ else
+ resendcount[netnode]--;
+
+ //
+ // check for out of order / duplicated packet
+ //
+ if (realend == nettics[netnode])
+ continue;
+
+ if (realend < nettics[netnode])
+ {
+ if (debugfile)
+ fprintf(debugfile, "out of order packet (%i + %i)\n",
+ realstart, netbuffer->numtics);
+ continue;
+ }
+
+ //
+ // check for a missed packet
+ //
+ if (realstart > nettics[netnode])
+ {
+ // stop processing until the other system resends the missed tics
+ if (debugfile)
+ fprintf(debugfile, "missed tics from %i (%i - %i)\n", netnode,
+ realstart, nettics[netnode]);
+ remoteresend[netnode] = true;
+ continue;
+ }
+
+//
+// update command store from the packet
+//
+ {
+ int start;
+
+ remoteresend[netnode] = false;
+
+ start = nettics[netnode] - realstart;
+ src = &netbuffer->cmds[start];
+
+ while (nettics[netnode] < realend)
+ {
+ dest = &netcmds[netconsole][nettics[netnode] % BACKUPTICS];
+ nettics[netnode]++;
+ *dest = *src;
+ src++;
+ }
+ }
+ }
+
+}
+
+/*
+=============
+=
+= NetUpdate
+=
+= Builds ticcmds for console player
+= sends out a packet
+=============
+*/
+
+int gametime;
+
+void NetUpdate(void)
+{
+ int nowtime;
+ int newtics;
+ int i, j;
+ int realstart;
+ int gameticdiv;
+
+//
+// check time
+//
+ nowtime = I_GetTime() / ticdup;
+ newtics = nowtime - gametime;
+ gametime = nowtime;
+
+ if (newtics <= 0) // nothing new to update
+ goto listen;
+
+ if (skiptics <= newtics)
+ {
+ newtics -= skiptics;
+ skiptics = 0;
+ }
+ else
+ {
+ skiptics -= newtics;
+ newtics = 0;
+ }
+
+
+ netbuffer->player = consoleplayer;
+
+//
+// build new ticcmds for console player
+//
+ gameticdiv = gametic / ticdup;
+ for (i = 0; i < newtics; i++)
+ {
+ I_StartTic();
+ D_ProcessEvents();
+ if (maketic - gameticdiv >= BACKUPTICS / 2 - 1)
+ break; // can't hold any more
+//printf ("mk:%i ",maketic);
+ G_BuildTiccmd(&localcmds[maketic % BACKUPTICS]);
+ maketic++;
+ }
+
+
+ if (singletics)
+ return; // singletic update is syncronous
+
+//
+// send the packet to the other nodes
+//
+ for (i = 0; i < doomcom->numnodes; i++)
+ if (nodeingame[i])
+ {
+ netbuffer->starttic = realstart = resendto[i];
+ netbuffer->numtics = maketic - realstart;
+ if (netbuffer->numtics > BACKUPTICS)
+ I_Error("NetUpdate: netbuffer->numtics > BACKUPTICS");
+
+ resendto[i] = maketic - doomcom->extratics;
+
+ for (j = 0; j < netbuffer->numtics; j++)
+ netbuffer->cmds[j] = localcmds[(realstart + j) % BACKUPTICS];
+
+ if (remoteresend[i])
+ {
+ netbuffer->retransmitfrom = nettics[i];
+ HSendPacket(i, NCMD_RETRANSMIT);
+ }
+ else
+ {
+ netbuffer->retransmitfrom = 0;
+ HSendPacket(i, 0);
+ }
+ }
+
+//
+// listen for other packets
+//
+ listen:
+
+ GetPackets();
+}
+
+
+/*
+=====================
+=
+= CheckAbort
+=
+=====================
+*/
+
+void CheckAbort(void)
+{
+ event_t *ev;
+ int stoptic;
+
+ stoptic = I_GetTime() + 2;
+ while (I_GetTime() < stoptic)
+ I_StartTic();
+
+ I_StartTic();
+ for (; eventtail != eventhead;
+ eventtail = (++eventtail) & (MAXEVENTS - 1))
+ {
+ ev = &events[eventtail];
+ if (ev->type == ev_keydown && ev->data1 == KEY_ESCAPE)
+ I_Error("Network game synchronization aborted.");
+ }
+}
+
+/*
+=====================
+=
+= D_ArbitrateNetStart
+=
+=====================
+*/
+
+void D_ArbitrateNetStart(void)
+{
+ int i;
+ boolean gotinfo[MAXNETNODES];
+
+ autostart = true;
+ memset(gotinfo, 0, sizeof(gotinfo));
+
+ if (doomcom->consoleplayer)
+ { // listen for setup info from key player
+// mprintf ("listening for network start info...\n");
+ while (1)
+ {
+ CheckAbort();
+ if (!HGetPacket())
+ continue;
+ if (netbuffer->checksum & NCMD_SETUP)
+ {
+ if (netbuffer->player != VERSION)
+ I_Error
+ ("Different DOOM versions cannot play a net game!");
+ startskill = netbuffer->retransmitfrom & 15;
+ deathmatch = (netbuffer->retransmitfrom & 0xc0) >> 6;
+ nomonsters = (netbuffer->retransmitfrom & 0x20) > 0;
+ respawnparm = (netbuffer->retransmitfrom & 0x10) > 0;
+ //startmap = netbuffer->starttic & 0x3f;
+ //startepisode = netbuffer->starttic >> 6;
+ startmap = netbuffer->starttic & 15;
+ startepisode = netbuffer->starttic >> 4;
+ return;
+ }
+ }
+ }
+ else
+ { // key player, send the setup info
+// mprintf ("sending network start info...\n");
+ do
+ {
+ CheckAbort();
+ for (i = 0; i < doomcom->numnodes; i++)
+ {
+ netbuffer->retransmitfrom = startskill;
+ if (deathmatch)
+ netbuffer->retransmitfrom |= (deathmatch << 6);
+ if (nomonsters)
+ netbuffer->retransmitfrom |= 0x20;
+ if (respawnparm)
+ netbuffer->retransmitfrom |= 0x10;
+ //netbuffer->starttic = startepisode * 64 + startmap;
+ netbuffer->starttic = (startepisode << 4) + startmap;
+ netbuffer->player = VERSION;
+ netbuffer->numtics = 0;
+ HSendPacket(i, NCMD_SETUP);
+ }
+
+#if 1
+ for (i = 10; i && HGetPacket(); --i)
+ {
+ if ((netbuffer->player & 0x7f) < MAXNETNODES)
+ gotinfo[netbuffer->player & 0x7f] = true;
+ }
+#else
+ while (HGetPacket())
+ {
+ gotinfo[netbuffer->player & 0x7f] = true;
+ }
+#endif
+
+ for (i = 1; i < doomcom->numnodes; i++)
+ if (!gotinfo[i])
+ break;
+ }
+ while (i < doomcom->numnodes);
+ }
+}
+
+/*
+===================
+=
+= D_CheckNetGame
+=
+= Works out player numbers among the net participants
+===================
+*/
+
+extern int viewangleoffset;
+
+void D_CheckNetGame(void)
+{
+ int i;
+
+ for (i = 0; i < MAXNETNODES; i++)
+ {
+ nodeingame[i] = false;
+ nettics[i] = 0;
+ remoteresend[i] = false; // set when local needs tics
+ resendto[i] = 0; // which tic to start sending
+ }
+
+// I_InitNetwork sets doomcom and netgame
+ I_InitNetwork();
+ if (doomcom->id != DOOMCOM_ID)
+ I_Error("Doomcom buffer invalid!");
+ netbuffer = &doomcom->data;
+ consoleplayer = displayplayer = doomcom->consoleplayer;
+ if (netgame)
+ D_ArbitrateNetStart();
+//printf ("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", startskill, deathmatch, startmap, startepisode);
+
+// read values out of doomcom
+ ticdup = doomcom->ticdup;
+ maxsend = BACKUPTICS / (2 * ticdup) - 1;
+ if (maxsend < 1)
+ maxsend = 1;
+
+ for (i = 0; i < doomcom->numplayers; i++)
+ playeringame[i] = true;
+ for (i = 0; i < doomcom->numnodes; i++)
+ nodeingame[i] = true;
+
+//printf ("player %i of %i (%i nodes)\n", consoleplayer+1, doomcom->numplayers, doomcom->numnodes);
+
+}
+
+/*
+==================
+=
+= D_QuitNetGame
+=
+= Called before quitting to leave a net game without hanging the
+= other players
+=
+==================
+*/
+
+void D_QuitNetGame(void)
+{
+ int i, j;
+
+ if (debugfile)
+ fclose(debugfile);
+
+ if (!netgame || !usergame || consoleplayer == -1 || demoplayback)
+ return;
+
+// send a bunch of packets for security
+ netbuffer->player = consoleplayer;
+ netbuffer->numtics = 0;
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 1; j < doomcom->numnodes; j++)
+ if (nodeingame[j])
+ HSendPacket(j, NCMD_EXIT);
+ I_WaitVBL(1);
+ }
+}
+
+
+
+/*
+===============
+=
+= TryRunTics
+=
+===============
+*/
+
+int frametics[4], frameon;
+int frameskip[4];
+int oldnettics;
+extern boolean advancedemo;
+
+void TryRunTics(void)
+{
+ int i;
+ int lowtic;
+ int entertic;
+ static int oldentertics;
+ int realtics, availabletics;
+ int counts;
+ int numplaying;
+
+//
+// get real tics
+//
+ entertic = I_GetTime() / ticdup;
+ realtics = entertic - oldentertics;
+ oldentertics = entertic;
+
+//
+// get available tics
+//
+ NetUpdate();
+
+ lowtic = MAXINT;
+ numplaying = 0;
+ for (i = 0; i < doomcom->numnodes; i++)
+ if (nodeingame[i])
+ {
+ numplaying++;
+ if (nettics[i] < lowtic)
+ lowtic = nettics[i];
+ }
+ availabletics = lowtic - gametic / ticdup;
+
+
+//
+// decide how many tics to run
+//
+ if (realtics < availabletics - 1)
+ counts = realtics + 1;
+ else if (realtics < availabletics)
+ counts = realtics;
+ else
+ counts = availabletics;
+ if (counts < 1)
+ counts = 1;
+
+ frameon++;
+
+ if (debugfile)
+ fprintf(debugfile, "=======real: %i avail: %i game: %i\n", realtics,
+ availabletics, counts);
+
+ if (!demoplayback)
+ {
+ //=============================================================================
+ //
+ // ideally nettics[0] should be 1 - 3 tics above lowtic
+ // if we are consistantly slower, speed up time
+ //
+ for (i = 0; i < MAXPLAYERS; i++)
+ if (playeringame[i])
+ break;
+ if (consoleplayer == i)
+ { // the key player does not adapt
+ }
+ else
+ {
+ if (nettics[0] <= nettics[nodeforplayer[i]])
+ {
+ gametime--;
+ // printf ("-");
+ }
+ frameskip[frameon & 3] = (oldnettics > nettics[nodeforplayer[i]]);
+ oldnettics = nettics[0];
+ if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
+ {
+ skiptics = 1;
+ // printf ("+");
+ }
+ }
+ //=============================================================================
+ } // demoplayback
+
+ //
+ // wait for new tics if needed
+ //
+ while (lowtic < gametic / ticdup + counts)
+ {
+
+ NetUpdate();
+ lowtic = MAXINT;
+
+ for (i = 0; i < doomcom->numnodes; i++)
+ if (nodeingame[i] && nettics[i] < lowtic)
+ lowtic = nettics[i];
+
+ if (lowtic < gametic / ticdup)
+ I_Error("TryRunTics: lowtic < gametic");
+
+ // don't stay in here forever -- give the menu a chance to work
+ if (I_GetTime() / ticdup - entertic >= 20)
+ {
+ MN_Ticker();
+ return;
+ }
+ }
+
+//
+// run the count * ticdup dics
+//
+ while (counts--)
+ {
+ for (i = 0; i < ticdup; i++)
+ {
+ if (gametic / ticdup > lowtic)
+ I_Error("gametic>lowtic");
+ if (advancedemo)
+ D_DoAdvanceDemo();
+ MN_Ticker();
+ G_Ticker();
+ gametic++;
+ //
+ // modify command for duplicated tics
+ //
+ if (i != ticdup - 1)
+ {
+ ticcmd_t *cmd;
+ int buf;
+ int j;
+
+ buf = (gametic / ticdup) % BACKUPTICS;
+ for (j = 0; j < MAXPLAYERS; j++)
+ {
+ cmd = &netcmds[j][buf];
+ cmd->chatchar = 0;
+ if (cmd->buttons & BT_SPECIAL)
+ cmd->buttons = 0;
+ }
+ }
+ }
+ NetUpdate(); // check for new console commands
+ }
+}