Iskhodnyy_kod_Doom
.pdfdest = &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 |
91
// 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]; |
92
autostart = true;
memset (gotinfo,0,sizeof(gotinfo));
if (doomcom->consoleplayer)
{
// listen for setup info from key player
printf ("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; return;
}
}
}
else
{
// key player, send the setup info
printf ("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->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);
93
}
}
//
//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;
94
// 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]; |
|
int |
frameon; |
|
int |
frameskip[4]; |
|
int |
oldnettics; |
|
extern |
boolean |
advancedemo; |
void TryRunTics (void) |
|
|
{ |
|
|
int |
|
i; |
int |
|
lowtic; |
int |
|
entertic; |
static int |
oldentertics; |
|
int |
|
realtics; |
int |
|
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;
95
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)
{
M_Ticker (); return;
}
}
// run the count * ticdup dics while (counts--)
{
for (i=0 ; i<ticdup ; i++)
{
if (gametic/ticdup > lowtic)
96
I_Error ("gametic>lowtic"); if (advancedemo)
D_DoAdvanceDemo ();
M_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 |
}
}
3.9d net.h
// Emacs style mode select -*- C++ -*- //-----------------------------------------------------------------------------
//
//$Id:$
//Copyright (C) 1993-1996 by id Software, Inc.
//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.
//
//DESCRIPTION:
//Networking stuff.
//-----------------------------------------------------------------------------
#ifndef __D_NET__ #define __D_NET__
#include "d_player.h"
#ifdef __GNUG__ #pragma interface #endif
//
97
//Network play related stuff.
//There is a data struct that stores network
//communication related stuff, and another
//one that defines the actual packets to
//be transmitted.
//
#define DOOMCOM_ID |
0x12345678l |
// Max computers/players in a game. |
|
#define MAXNETNODES |
8 |
// Networking and tick handling related. |
|
#define BACKUPTICS |
12 |
typedef enum |
|
{ |
|
CMD_SEND |
= 1, |
CMD_GET |
= 2 |
} command_t;
//
// Network packet data.
//
typedef struct
{
// High bit is retransmit request.
unsigned |
checksum; |
// Only valid if NCMD_RETRANSMIT. |
|
byte |
retransmitfrom; |
byte |
starttic; |
byte |
player; |
byte |
numtics; |
ticcmd_t |
cmds[BACKUPTICS]; |
} doomdata_t;
typedef struct
{
// |
Supposed to be DOOMCOM_ID? |
|
long |
id; |
|
// |
DOOM executes an int to execute commands. |
|
short |
intnum; |
//Communication between DOOM and the driver.
//Is CMD_SEND or CMD_GET.
short |
command; |
|
// |
Is dest for send, set by get (-1 = no packet). |
|
short |
remotenode; |
|
// |
Number of bytes in doomdata to be sent |
|
short |
datalength; |
//Info common to all nodes.
//Console is allways node 0.
short |
numnodes; |
|
// Flag: 1 = no duplication, |
2-5 = dup for slow nets. |
|
short |
ticdup; |
|
98
// Flag: 1 = send a backup tic in every packet.
short |
extratics; |
|
// Flag: 1 = deathmatch. |
|
|
short |
deathmatch; |
|
// Flag: -1 = new game, 0-5 = load savegame |
||
short |
savegame; |
|
short |
episode; |
// 1-3 |
short |
map; |
// 1-9 |
short |
skill; |
// 1-5 |
// Info specific to this node. |
|
|
short |
consoleplayer; |
|
short |
numplayers; |
|
//These are related to the 3-display mode,
//in which two drones looking left and right
//were used to render two additional views
//on two additional computers.
//Probably not operational anymore.
//1 = left, 0 = center, -1 = right
short |
|
angleoffset; |
|
// |
1 = |
drone |
|
short |
|
drone; |
|
// |
The |
packet data to be sent. |
|
doomdata_t |
data; |
} doomcom_t;
//Create any new ticcmds and broadcast to other players. void NetUpdate (void);
//Broadcasts special packets to other players
//to notify of game exit
void D_QuitNetGame (void);
//? how many ticks to run? void TryRunTics (void);
#endif
//-----------------------------------------------------------------------------
//
// $Log:$
//
//-----------------------------------------------------------------------------
3.10 d player.h
// Emacs style mode select -*- C++ -*- //-----------------------------------------------------------------------------
//
//$Id:$
//Copyright (C) 1993-1996 by id Software, Inc.
//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.
//
99
//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.
//
// DESCRIPTION:
//
//
//-----------------------------------------------------------------------------
#ifndef __D_PLAYER__ #define __D_PLAYER__
//The player data structure depends on a number
//of other structs: items (internal inventory),
//animation states (closely tied to the sprites
//used to represent them, unfortunately). #include "d_items.h"
#include "p_pspr.h"
//In addition, the player is just a special
//case of the generic moving object/actor. #include "p_mobj.h"
//Finally, for odd reasons, the player input
//is buffered within the player data struct,
//as commands per game tick.
#include "d_ticcmd.h"
#ifdef __GNUG__ #pragma interface #endif
//
// Player states.
//
typedef enum
{
//Playing or camping. PST_LIVE,
//Dead on the ground, view follows killer. PST_DEAD,
//Ready to restart/respawn???
PST_REBORN
} playerstate_t;
//
// Player internal flags, for cheats and debug.
//
typedef enum
{
// No clipping, walk through barriers.
CF_NOCLIP |
|
= 1, |
||
// |
No damage, |
no health loss. |
||
CF_GODMODE |
|
= |
2, |
|
// |
Not really |
a cheat, |
just |
a debug aid. |
CF_NOMOMENTUM |
= |
4 |
|
100