Squashed 'external/pure_doom/PureDOOM/' content from commit 5694fa4
git-subtree-dir: external/pure_doom/PureDOOM git-subtree-split: 5694fa42089714cb3c9edc1c8e10e4e6b6e9adb9
This commit is contained in:
856
src/DOOM/d_net.c
Normal file
856
src/DOOM/d_net.c
Normal file
@@ -0,0 +1,856 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// DOOM Network game communication and protocol,
|
||||
// all OS independend parts.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
|
||||
|
||||
#include "m_menu.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
#include "i_net.h"
|
||||
#include "g_game.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
|
||||
//
|
||||
// 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 NCMD_EXIT 0x80000000
|
||||
#define NCMD_RETRANSMIT 0x40000000
|
||||
#define NCMD_SETUP 0x20000000
|
||||
#define NCMD_KILL 0x10000000 // kill game
|
||||
#define NCMD_CHECKSUM 0x0fffffff
|
||||
|
||||
#define RESENDCOUNT 10
|
||||
#define PL_DRONE 0x80 // bit flag in doomdata->player
|
||||
|
||||
|
||||
doomcom_t* doomcom;
|
||||
doomdata_t* netbuffer; // points inside doomcom
|
||||
|
||||
ticcmd_t localcmds[BACKUPTICS];
|
||||
|
||||
ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
|
||||
int nettics[MAXNETNODES];
|
||||
doom_boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
|
||||
doom_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;
|
||||
int skiptics;
|
||||
int ticdup;
|
||||
int maxsend; // BACKUPTICS/(2*ticdup)-1
|
||||
|
||||
doom_boolean reboundpacket;
|
||||
doomdata_t reboundstore;
|
||||
|
||||
char exitmsg[80];
|
||||
int gametime;
|
||||
int frametics[4];
|
||||
int frameon;
|
||||
int frameskip[4];
|
||||
int oldnettics;
|
||||
|
||||
|
||||
extern int viewangleoffset;
|
||||
extern doom_boolean advancedemo;
|
||||
|
||||
|
||||
void D_ProcessEvents(void);
|
||||
void G_BuildTiccmd(ticcmd_t* cmd);
|
||||
void D_DoAdvanceDemo(void);
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
int NetbufferSize(void)
|
||||
{
|
||||
return (int)(long long)&(((doomdata_t*)0)->cmds[netbuffer->numtics]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Checksum
|
||||
//
|
||||
unsigned NetbufferChecksum(void)
|
||||
{
|
||||
unsigned c;
|
||||
int i, l;
|
||||
|
||||
c = 0x1234567;
|
||||
|
||||
// FIXME -endianess?
|
||||
// #ifdef NORMALUNIX
|
||||
return 0; // byte order problems
|
||||
// #endif
|
||||
|
||||
l = (NetbufferSize() - (int)(long long)&(((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("Error: ExpandTics: strange value %i at maketic %i", low, maketic);
|
||||
doom_strcpy(error_buf, "Error: ExpandTics: strange value ");
|
||||
doom_concat(error_buf, doom_itoa(low, 10));
|
||||
doom_concat(error_buf, " at maketic ");
|
||||
doom_concat(error_buf, doom_itoa(maketic, 10));
|
||||
I_Error(error_buf);
|
||||
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("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);
|
||||
doom_fprint(debugfile, "send (");
|
||||
doom_fprint(debugfile, doom_itoa(ExpandTics(netbuffer->starttic), 10));
|
||||
doom_fprint(debugfile, " + ");
|
||||
doom_fprint(debugfile, doom_itoa(netbuffer->numtics, 10));
|
||||
doom_fprint(debugfile, ", R ");
|
||||
doom_fprint(debugfile, doom_itoa(realretrans, 10));
|
||||
doom_fprint(debugfile, ") [");
|
||||
doom_fprint(debugfile, doom_itoa(doomcom->datalength, 10));
|
||||
doom_fprint(debugfile, "] ");
|
||||
}
|
||||
|
||||
for (i = 0; i < doomcom->datalength; i++)
|
||||
{
|
||||
//fprintf(debugfile, "%i ", ((byte*)netbuffer)[i]);
|
||||
doom_fprint(debugfile, doom_itoa(((byte*)netbuffer)[i], 10));
|
||||
doom_fprint(debugfile, " ");
|
||||
}
|
||||
|
||||
doom_fprint(debugfile, "\n");
|
||||
}
|
||||
|
||||
I_NetCmd();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// HGetPacket
|
||||
// Returns false if no packet is waiting
|
||||
//
|
||||
doom_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);
|
||||
doom_fprint(debugfile, "bad packet length ");
|
||||
doom_fprint(debugfile, doom_itoa(doomcom->datalength, 10));
|
||||
doom_fprint(debugfile, "\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NetbufferChecksum() != (netbuffer->checksum & NCMD_CHECKSUM))
|
||||
{
|
||||
if (debugfile)
|
||||
{
|
||||
doom_fprint(debugfile, "bad packet checksum\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
int realretrans;
|
||||
int i;
|
||||
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
{
|
||||
doom_fprint(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);
|
||||
doom_fprint(debugfile, "get ");
|
||||
doom_fprint(debugfile, doom_itoa(doomcom->remotenode, 10));
|
||||
doom_fprint(debugfile, " = (");
|
||||
doom_fprint(debugfile, doom_itoa(ExpandTics(netbuffer->starttic), 10));
|
||||
doom_fprint(debugfile, " + ");
|
||||
doom_fprint(debugfile, doom_itoa(netbuffer->numtics, 10));
|
||||
doom_fprint(debugfile, ", R ");
|
||||
doom_fprint(debugfile, doom_itoa(realretrans, 10));
|
||||
doom_fprint(debugfile, ")[");
|
||||
doom_fprint(debugfile, doom_itoa(doomcom->datalength, 10));
|
||||
doom_fprint(debugfile, "] ");
|
||||
}
|
||||
|
||||
for (i = 0; i < doomcom->datalength; i++)
|
||||
{
|
||||
//fprintf(debugfile, "%i ", ((byte*)netbuffer)[i]);
|
||||
doom_fprint(debugfile, doom_itoa(((byte*)netbuffer)[i], 10));
|
||||
doom_fprint(debugfile, " ");
|
||||
}
|
||||
doom_fprint(debugfile, "\n");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetPackets
|
||||
//
|
||||
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;
|
||||
doom_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("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]);
|
||||
doom_fprint(debugfile, "retransmit from ");
|
||||
doom_fprint(debugfile, doom_itoa(resendto[netnode], 10));
|
||||
doom_fprint(debugfile, "\n");
|
||||
}
|
||||
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);
|
||||
doom_fprint(debugfile, "out of order packet (");
|
||||
doom_fprint(debugfile, doom_itoa(realstart, 10));
|
||||
doom_fprint(debugfile, " + ");
|
||||
doom_fprint(debugfile, doom_itoa(netbuffer->numtics, 10));
|
||||
doom_fprint(debugfile, ")\n");
|
||||
}
|
||||
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]);
|
||||
doom_fprint(debugfile, "missed tics from ");
|
||||
doom_fprint(debugfile, doom_itoa(netnode, 10));
|
||||
doom_fprint(debugfile, " (");
|
||||
doom_fprint(debugfile, doom_itoa(realstart, 10));
|
||||
doom_fprint(debugfile, " - ");
|
||||
doom_fprint(debugfile, doom_itoa(nettics[netnode], 10));
|
||||
doom_fprint(debugfile, ")\n");
|
||||
}
|
||||
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
|
||||
//
|
||||
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
|
||||
|
||||
//doom_print ("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("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
|
||||
; )
|
||||
{
|
||||
ev = &events[eventtail];
|
||||
if (ev->type == ev_keydown && ev->data1 == KEY_ESCAPE)
|
||||
I_Error("Error: Network game synchronization aborted.");
|
||||
}
|
||||
|
||||
eventtail++;
|
||||
eventtail = (eventtail) & (MAXEVENTS - 1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// D_ArbitrateNetStart
|
||||
//
|
||||
void D_ArbitrateNetStart(void)
|
||||
{
|
||||
int i;
|
||||
doom_boolean gotinfo[MAXNETNODES];
|
||||
|
||||
autostart = true;
|
||||
doom_memset(gotinfo, 0, sizeof(gotinfo));
|
||||
|
||||
if (doomcom->consoleplayer)
|
||||
{
|
||||
// listen for setup info from key player
|
||||
doom_print("listening for network start info...\n");
|
||||
while (1)
|
||||
{
|
||||
CheckAbort();
|
||||
if (!HGetPacket())
|
||||
continue;
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
{
|
||||
if (netbuffer->player != VERSION)
|
||||
I_Error("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
|
||||
doom_print("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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// D_CheckNetGame
|
||||
// Works out player numbers among the net participants
|
||||
//
|
||||
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("Error: Doomcom buffer invalid!");
|
||||
|
||||
netbuffer = &doomcom->data;
|
||||
consoleplayer = displayplayer = doomcom->consoleplayer;
|
||||
if (netgame)
|
||||
D_ArbitrateNetStart();
|
||||
|
||||
//doom_print("startskill %i deathmatch: %i startmap: %i startepisode: %i\n",
|
||||
// startskill, deathmatch, startmap, startepisode);
|
||||
doom_print("startskill ");
|
||||
doom_print(doom_itoa(startskill, 10));
|
||||
doom_print(" deathmatch: ");
|
||||
doom_print(doom_itoa(deathmatch, 10));
|
||||
doom_print(" startmap: ");
|
||||
doom_print(doom_itoa(startmap, 10));
|
||||
doom_print(" startepisode: ");
|
||||
doom_print(doom_itoa(startepisode, 10));
|
||||
doom_print("\n");
|
||||
|
||||
// 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;
|
||||
|
||||
//doom_print("player %i of %i (%i nodes)\n",
|
||||
// consoleplayer + 1, doomcom->numplayers, doomcom->numnodes);
|
||||
doom_print("player ");
|
||||
doom_print(doom_itoa(consoleplayer + 1, 10));
|
||||
doom_print(" of ");
|
||||
doom_print(doom_itoa(doomcom->numplayers, 10));
|
||||
doom_print(" (");
|
||||
doom_print(doom_itoa(doomcom->numnodes, 10));
|
||||
doom_print(" nodes)\n");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// D_QuitNetGame
|
||||
// Called before quitting to leave a net game
|
||||
// without hanging the other players
|
||||
//
|
||||
void D_QuitNetGame(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (debugfile)
|
||||
doom_close(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
|
||||
//
|
||||
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 = DOOM_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);
|
||||
doom_fprint(debugfile, "=======real: ");
|
||||
doom_fprint(debugfile, doom_itoa(realtics, 10));
|
||||
doom_fprint(debugfile, " avail: ");
|
||||
doom_fprint(debugfile, doom_itoa(availabletics, 10));
|
||||
doom_fprint(debugfile, " game: ");
|
||||
doom_fprint(debugfile, doom_itoa(counts, 10));
|
||||
doom_fprint(debugfile, "\n");
|
||||
}
|
||||
|
||||
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--;
|
||||
// doom_print ("-");
|
||||
}
|
||||
frameskip[frameon & 3] = (oldnettics > nettics[nodeforplayer[i]]);
|
||||
oldnettics = nettics[0];
|
||||
if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
|
||||
{
|
||||
skiptics = 1;
|
||||
// doom_print ("+");
|
||||
}
|
||||
}
|
||||
}// demoplayback
|
||||
|
||||
// wait for new tics if needed
|
||||
while (lowtic < gametic / ticdup + counts)
|
||||
{
|
||||
NetUpdate();
|
||||
lowtic = DOOM_MAXINT;
|
||||
|
||||
for (i = 0; i < doomcom->numnodes; i++)
|
||||
if (nodeingame[i] && nettics[i] < lowtic)
|
||||
lowtic = nettics[i];
|
||||
|
||||
if (lowtic < gametic / ticdup)
|
||||
I_Error("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)
|
||||
I_Error("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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user