📄 d_net.c
字号:
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];
boolean gotClass[MAXNETNODES];
#ifdef __WATCOMC__
int nextTic;
extern volatile int ticcount;
nextTic = ticcount+8;
#endif
autostart = true;
memset (gotClass,0,sizeof(gotClass));
memset (gotinfo,0,sizeof(gotinfo));
gotClass[doomcom->consoleplayer] = true;
do
{
i = 0;
CheckAbort();
while(HGetPacket())
{ // Check for any incoming packets
if(netbuffer->checksum&NCMD_SETUP && netbuffer->starttic >= 64)
{
PlayerClass[netbuffer->player] = netbuffer->starttic&0x3f;
if(!gotClass[netbuffer->player])
{
gotClass[netbuffer->player] = true;
ST_NetProgress();
ST_Message("\n");
}
if(netbuffer->retransmitfrom)
{ // that node has received info from all other nodes
gotinfo[netbuffer->player] = true;
}
}
}
#ifdef __WATCOMC__
if(ticcount <= nextTic)
{ // only send packets every half second
continue;
}
nextTic = ticcount+8;
#endif
// Keep sending out packets containing the console class
for(i = 0; i < doomcom->numnodes; i++)
{
netbuffer->player = doomcom->consoleplayer;
netbuffer->starttic = PlayerClass[doomcom->consoleplayer]+64;
netbuffer->retransmitfrom = gotinfo[doomcom->consoleplayer];
netbuffer->numtics = 0;
HSendPacket(i, NCMD_SETUP);
}
for(i = 0; i < doomcom->numnodes; i++)
{ // Make sure that all nodes have sent class info
if (!gotClass[i])
{
ST_Message(".");
break;
}
}
if(i < doomcom->numnodes)
{
continue;
}
else
{ // consoleplayer has received all player classes
if(gotinfo[doomcom->consoleplayer])
{
CheckAbort();
}
else
{
gotinfo[doomcom->consoleplayer] = true;
ST_Message("All player classes received, ready to proceed\n");
ST_NetDone();
}
}
for (i = 0; i < doomcom->numnodes; i++)
{ // Make sure that all nodes are ready to proceed
if (!gotinfo[i])
{
break;
}
}
} while(i < doomcom->numnodes);
memset (gotinfo,0,sizeof(gotinfo));
if (doomcom->consoleplayer)
{ // listen for setup info from key player
// ST_Message ("listening for network start info...\n");
while (1)
{
CheckAbort ();
if (!HGetPacket ())
continue;
if(netbuffer->checksum & NCMD_SETUP && netbuffer->starttic < 64)
{
if (netbuffer->player != VERSION)
I_Error ("Different HEXEN 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 = 1;
return;
}
}
}
else
{ // key player, send the setup info
// ST_Message ("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 = startmap&0x3f;
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;
int pClass;
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;
pClass = PCLASS_FIGHTER;
if(i = M_CheckParm("-class"))
{
pClass = atoi(myargv[i+1]);
if(pClass > PCLASS_MAGE || pClass < PCLASS_FIGHTER)
{
I_Error("Invalid player class: %d\n", pClass);
}
ST_Message("\nPlayer Class: %d\n", pClass);
}
PlayerClass[consoleplayer] = pClass;
if (netgame)
D_ArbitrateNetStart ();
//ST_Message ("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;
//ST_Message ("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)
H2_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
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -