2006-02-24 04:48:15 +00:00
|
|
|
// 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 independent parts.
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
#include "version.h"
|
2010-09-14 17:28:18 +00:00
|
|
|
#include "menu/menu.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
#include "m_random.h"
|
|
|
|
#include "i_system.h"
|
|
|
|
#include "i_video.h"
|
|
|
|
#include "i_net.h"
|
|
|
|
#include "g_game.h"
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
#include "c_console.h"
|
|
|
|
#include "d_netinf.h"
|
2008-09-14 23:54:38 +00:00
|
|
|
#include "d_net.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
#include "cmdlib.h"
|
|
|
|
#include "s_sound.h"
|
|
|
|
#include "m_cheat.h"
|
|
|
|
#include "p_local.h"
|
|
|
|
#include "c_dispatch.h"
|
|
|
|
#include "sbar.h"
|
|
|
|
#include "gi.h"
|
|
|
|
#include "m_misc.h"
|
|
|
|
#include "gameconfigfile.h"
|
|
|
|
#include "d_gui.h"
|
|
|
|
#include "templates.h"
|
|
|
|
#include "p_acs.h"
|
2006-04-21 05:44:21 +00:00
|
|
|
#include "p_trace.h"
|
|
|
|
#include "a_sharedglobal.h"
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
#include "st_start.h"
|
2007-12-20 20:22:31 +00:00
|
|
|
#include "teaminfo.h"
|
2008-03-26 08:29:02 +00:00
|
|
|
#include "p_conversation.h"
|
2008-09-14 23:54:38 +00:00
|
|
|
#include "g_level.h"
|
|
|
|
#include "d_event.h"
|
2008-09-15 00:47:31 +00:00
|
|
|
#include "m_argv.h"
|
2011-01-02 18:54:57 +00:00
|
|
|
#include "p_lnspec.h"
|
2011-07-05 10:02:38 +00:00
|
|
|
#include "v_video.h"
|
2012-02-26 03:36:05 +00:00
|
|
|
#include "p_spec.h"
|
2012-09-16 04:40:56 +00:00
|
|
|
#include "hardware.h"
|
2011-12-06 02:51:32 +00:00
|
|
|
#include "intermission/intermission.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-10-19 20:20:56 +00:00
|
|
|
EXTERN_CVAR (Int, disableautosave)
|
|
|
|
EXTERN_CVAR (Int, autosavecount)
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//#define SIMULATEERRORS (RAND_MAX/3)
|
|
|
|
#define SIMULATEERRORS 0
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
extern BYTE *demo_p; // [RH] Special "ticcmds" get recorded in demos
|
2006-02-24 04:48:15 +00:00
|
|
|
extern char savedescription[SAVESTRINGSIZE];
|
2006-05-03 22:45:01 +00:00
|
|
|
extern FString savegamefile;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
extern short consistancy[MAXPLAYERS][BACKUPTICS];
|
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
doomcom_t doomcom;
|
|
|
|
#define netbuffer (doomcom.data)
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
enum { NET_PeerToPeer, NET_PacketServer };
|
|
|
|
BYTE NetMode = NET_PeerToPeer;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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[LOCALCMDTICS];
|
|
|
|
|
|
|
|
FDynamicBuffer NetSpecs[MAXPLAYERS][BACKUPTICS];
|
|
|
|
ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
|
|
|
|
int nettics[MAXNETNODES];
|
2006-09-14 00:02:31 +00:00
|
|
|
bool nodeingame[MAXNETNODES]; // set false as nodes leave game
|
2006-02-24 04:48:15 +00:00
|
|
|
bool nodejustleft[MAXNETNODES]; // set when a node just left
|
2006-09-14 00:02:31 +00:00
|
|
|
bool remoteresend[MAXNETNODES]; // set when local needs tics
|
2006-02-24 04:48:15 +00:00
|
|
|
int resendto[MAXNETNODES]; // set when remote needs tics
|
|
|
|
int resendcount[MAXNETNODES];
|
|
|
|
|
|
|
|
unsigned int lastrecvtime[MAXPLAYERS]; // [RH] Used for pings
|
|
|
|
unsigned int currrecvtime[MAXPLAYERS];
|
2015-02-09 20:16:57 +00:00
|
|
|
unsigned int lastglobalrecvtime; // Identify the last time a packet was received.
|
2013-05-25 22:01:26 +00:00
|
|
|
bool hadlate;
|
2014-08-19 10:30:33 +00:00
|
|
|
int netdelay[MAXNETNODES][BACKUPTICS]; // Used for storing network delay times.
|
2014-09-26 03:37:14 +00:00
|
|
|
int lastaverage;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
int nodeforplayer[MAXPLAYERS];
|
|
|
|
int playerfornode[MAXNETNODES];
|
|
|
|
|
|
|
|
int maketic;
|
|
|
|
int skiptics;
|
2014-08-18 09:46:48 +00:00
|
|
|
int ticdup;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
void D_ProcessEvents (void);
|
|
|
|
void G_BuildTiccmd (ticcmd_t *cmd);
|
|
|
|
void D_DoAdvanceDemo (void);
|
|
|
|
|
|
|
|
static void SendSetup (DWORD playersdetected[MAXNETNODES], BYTE gotsetup[MAXNETNODES], int len);
|
2012-02-26 03:36:05 +00:00
|
|
|
static void RunScript(BYTE **stream, APlayerPawn *pawn, int snum, int argn, int always);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
int reboundpacket;
|
|
|
|
BYTE reboundstore[MAX_MSGLEN];
|
|
|
|
|
|
|
|
int frameon;
|
|
|
|
int frameskip[4];
|
|
|
|
int oldnettics;
|
|
|
|
int mastertics;
|
|
|
|
|
|
|
|
static int entertic;
|
|
|
|
static int oldentertics;
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
extern bool advancedemo;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2012-09-16 04:40:56 +00:00
|
|
|
CUSTOM_CVAR (Bool, cl_capfps, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|
|
|
{
|
|
|
|
// Do not use the separate FPS limit timer if we are limiting FPS with this.
|
|
|
|
if (self)
|
|
|
|
{
|
|
|
|
I_SetFPSLimit(0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
I_SetFPSLimit(-1);
|
|
|
|
}
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2014-08-26 10:31:42 +00:00
|
|
|
CVAR(Bool, net_ticbalance, false, CVAR_SERVERINFO | CVAR_NOSAVE)
|
|
|
|
CUSTOM_CVAR(Int, net_extratic, 0, CVAR_SERVERINFO | CVAR_NOSAVE)
|
2014-08-18 09:46:48 +00:00
|
|
|
{
|
|
|
|
if (self < 0)
|
|
|
|
{
|
|
|
|
self = 0;
|
|
|
|
}
|
2014-08-18 10:45:51 +00:00
|
|
|
else if (self > 2)
|
2014-08-18 09:46:48 +00:00
|
|
|
{
|
2014-08-18 10:45:51 +00:00
|
|
|
self = 2;
|
2014-08-18 09:46:48 +00:00
|
|
|
}
|
|
|
|
}
|
2014-08-16 09:15:39 +00:00
|
|
|
|
2014-08-26 10:31:42 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
CVAR(Int, net_fakelatency, 0, 0);
|
|
|
|
|
|
|
|
struct PacketStore
|
|
|
|
{
|
|
|
|
int timer;
|
|
|
|
doomcom_t message;
|
|
|
|
};
|
|
|
|
|
|
|
|
static TArray<PacketStore> InBuffer;
|
|
|
|
static TArray<PacketStore> OutBuffer;
|
|
|
|
#endif
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// [RH] Special "ticcmds" get stored in here
|
|
|
|
static struct TicSpecial
|
|
|
|
{
|
2006-09-14 00:02:31 +00:00
|
|
|
BYTE *streams[BACKUPTICS];
|
2006-02-24 04:48:15 +00:00
|
|
|
size_t used[BACKUPTICS];
|
2006-09-14 00:02:31 +00:00
|
|
|
BYTE *streamptr;
|
2006-02-24 04:48:15 +00:00
|
|
|
size_t streamoffs;
|
2015-01-01 23:57:09 +00:00
|
|
|
size_t specialsize;
|
2006-02-24 04:48:15 +00:00
|
|
|
int lastmaketic;
|
2006-09-14 00:02:31 +00:00
|
|
|
bool okay;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
TicSpecial ()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
lastmaketic = -1;
|
|
|
|
specialsize = 256;
|
|
|
|
|
|
|
|
for (i = 0; i < BACKUPTICS; i++)
|
|
|
|
streams[i] = NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < BACKUPTICS; i++)
|
|
|
|
{
|
2006-09-14 00:02:31 +00:00
|
|
|
streams[i] = (BYTE *)M_Malloc (256);
|
2006-02-24 04:48:15 +00:00
|
|
|
used[i] = 0;
|
|
|
|
}
|
|
|
|
okay = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
~TicSpecial ()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < BACKUPTICS; i++)
|
|
|
|
{
|
|
|
|
if (streams[i])
|
|
|
|
{
|
2008-02-17 02:40:03 +00:00
|
|
|
M_Free (streams[i]);
|
2006-02-24 04:48:15 +00:00
|
|
|
streams[i] = NULL;
|
|
|
|
used[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
okay = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make more room for special commands.
|
2015-01-01 23:57:09 +00:00
|
|
|
void GetMoreSpace (size_t needed)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2015-01-01 23:57:09 +00:00
|
|
|
specialsize = MAX(specialsize * 2, needed + 30);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2015-03-08 22:21:15 +00:00
|
|
|
DPrintf ("Expanding special size to %zu\n", specialsize);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
for (i = 0; i < BACKUPTICS; i++)
|
2006-09-14 00:02:31 +00:00
|
|
|
streams[i] = (BYTE *)M_Realloc (streams[i], specialsize);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
streamptr = streams[(maketic/ticdup)%BACKUPTICS] + streamoffs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheckSpace (size_t needed)
|
|
|
|
{
|
2015-01-01 23:57:09 +00:00
|
|
|
if (streamoffs + needed >= specialsize)
|
|
|
|
GetMoreSpace (streamoffs + needed);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
streamoffs += needed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewMakeTic ()
|
|
|
|
{
|
|
|
|
int mt = maketic / ticdup;
|
|
|
|
if (lastmaketic != -1)
|
|
|
|
{
|
|
|
|
if (lastmaketic == mt)
|
|
|
|
return;
|
|
|
|
used[lastmaketic%BACKUPTICS] = streamoffs;
|
|
|
|
}
|
|
|
|
|
|
|
|
lastmaketic = mt;
|
|
|
|
streamptr = streams[mt%BACKUPTICS];
|
|
|
|
streamoffs = 0;
|
|
|
|
}
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
TicSpecial &operator << (BYTE it)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (streamptr)
|
|
|
|
{
|
|
|
|
CheckSpace (1);
|
|
|
|
WriteByte (it, &streamptr);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
TicSpecial &operator << (short it)
|
|
|
|
{
|
|
|
|
if (streamptr)
|
|
|
|
{
|
|
|
|
CheckSpace (2);
|
|
|
|
WriteWord (it, &streamptr);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
TicSpecial &operator << (int it)
|
|
|
|
{
|
|
|
|
if (streamptr)
|
|
|
|
{
|
|
|
|
CheckSpace (4);
|
|
|
|
WriteLong (it, &streamptr);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
TicSpecial &operator << (float it)
|
|
|
|
{
|
|
|
|
if (streamptr)
|
|
|
|
{
|
|
|
|
CheckSpace (4);
|
|
|
|
WriteFloat (it, &streamptr);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
TicSpecial &operator << (const char *it)
|
|
|
|
{
|
|
|
|
if (streamptr)
|
|
|
|
{
|
|
|
|
CheckSpace (strlen (it) + 1);
|
|
|
|
WriteString (it, &streamptr);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
} specials;
|
|
|
|
|
|
|
|
void Net_ClearBuffers ()
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
memset (localcmds, 0, sizeof(localcmds));
|
|
|
|
memset (netcmds, 0, sizeof(netcmds));
|
|
|
|
memset (nettics, 0, sizeof(nettics));
|
|
|
|
memset (nodeingame, 0, sizeof(nodeingame));
|
|
|
|
memset (remoteresend, 0, sizeof(remoteresend));
|
|
|
|
memset (resendto, 0, sizeof(resendto));
|
|
|
|
memset (resendcount, 0, sizeof(resendcount));
|
|
|
|
memset (lastrecvtime, 0, sizeof(lastrecvtime));
|
|
|
|
memset (currrecvtime, 0, sizeof(currrecvtime));
|
|
|
|
memset (consistancy, 0, sizeof(consistancy));
|
|
|
|
nodeingame[0] = true;
|
|
|
|
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < BACKUPTICS; j++)
|
|
|
|
{
|
|
|
|
NetSpecs[i][j].SetData (NULL, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
oldentertics = entertic;
|
|
|
|
gametic = 0;
|
|
|
|
maketic = 0;
|
2013-05-25 22:01:26 +00:00
|
|
|
|
|
|
|
lastglobalrecvtime = 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// [RH] Rewritten to properly calculate the packet size
|
|
|
|
// with our variable length commands.
|
|
|
|
//
|
|
|
|
int NetbufferSize ()
|
|
|
|
{
|
|
|
|
if (netbuffer[0] & (NCMD_EXIT | NCMD_SETUP))
|
|
|
|
{
|
2006-05-11 04:00:58 +00:00
|
|
|
return doomcom.datalength;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int k = 2, count, numtics;
|
|
|
|
|
|
|
|
if (netbuffer[0] & NCMD_RETRANSMIT)
|
|
|
|
k++;
|
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
if (NetMode == NET_PacketServer && doomcom.remotenode == nodeforplayer[Net_Arbitrator])
|
2006-02-24 04:48:15 +00:00
|
|
|
k++;
|
|
|
|
|
|
|
|
numtics = netbuffer[0] & NCMD_XTICS;
|
|
|
|
if (numtics == 3)
|
|
|
|
{
|
|
|
|
numtics += netbuffer[k++];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (netbuffer[0] & NCMD_QUITTERS)
|
|
|
|
{
|
|
|
|
k += netbuffer[k] + 1;
|
|
|
|
}
|
|
|
|
|
2014-08-18 09:08:17 +00:00
|
|
|
// Network delay byte
|
|
|
|
k++;
|
2014-08-16 09:15:39 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (netbuffer[0] & NCMD_MULTI)
|
|
|
|
{
|
|
|
|
count = netbuffer[k];
|
|
|
|
k += count;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
count = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Need at least 3 bytes per tic per player
|
2006-05-11 04:00:58 +00:00
|
|
|
if (doomcom.datalength < k + 3 * count * numtics)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
return k + 3 * count * numtics;
|
|
|
|
}
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
BYTE *skipper = &netbuffer[k];
|
2006-02-24 04:48:15 +00:00
|
|
|
if ((netbuffer[0] & NCMD_EXIT) == 0)
|
|
|
|
{
|
|
|
|
while (count-- > 0)
|
|
|
|
{
|
|
|
|
SkipTicCmd (&skipper, numtics);
|
|
|
|
}
|
|
|
|
}
|
2009-05-15 10:39:40 +00:00
|
|
|
return int(skipper - netbuffer);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
int ExpandTics (int low)
|
|
|
|
{
|
|
|
|
int delta;
|
|
|
|
int mt = maketic / ticdup;
|
|
|
|
|
|
|
|
delta = low - (mt&0xff);
|
|
|
|
|
|
|
|
if (delta >= -64 && delta <= 64)
|
|
|
|
return (mt&~0xff) + low;
|
|
|
|
if (delta > 64)
|
|
|
|
return (mt&~0xff) - 256 + low;
|
|
|
|
if (delta < -64)
|
|
|
|
return (mt&~0xff) + 256 + low;
|
|
|
|
|
|
|
|
I_Error ("ExpandTics: strange value %i at maketic %i", low, maketic);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// HSendPacket
|
|
|
|
//
|
|
|
|
void HSendPacket (int node, int len)
|
|
|
|
{
|
|
|
|
if (debugfile && node != 0)
|
|
|
|
{
|
|
|
|
int i, k, realretrans;
|
|
|
|
|
|
|
|
if (netbuffer[0] & NCMD_SETUP)
|
|
|
|
{
|
|
|
|
fprintf (debugfile,"%i/%i send %i = SETUP [%3i]", gametic, maketic, node, len);
|
|
|
|
for (i = 0; i < len; i++)
|
2006-09-14 00:02:31 +00:00
|
|
|
fprintf (debugfile," %2x", ((BYTE *)netbuffer)[i]);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else if (netbuffer[0] & NCMD_EXIT)
|
|
|
|
{
|
|
|
|
fprintf (debugfile,"%i/%i send %i = EXIT [%3i]", gametic, maketic, node, len);
|
|
|
|
for (i = 0; i < len; i++)
|
2006-09-14 00:02:31 +00:00
|
|
|
fprintf (debugfile," %2x", ((BYTE *)netbuffer)[i]);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
k = 2;
|
|
|
|
|
|
|
|
if (NetMode == NET_PacketServer && consoleplayer == Net_Arbitrator &&
|
|
|
|
node != 0)
|
|
|
|
{
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (netbuffer[0] & NCMD_RETRANSMIT)
|
|
|
|
realretrans = ExpandTics (netbuffer[k++]);
|
|
|
|
else
|
|
|
|
realretrans = -1;
|
|
|
|
|
|
|
|
int numtics = netbuffer[0] & 3;
|
|
|
|
if (numtics == 3)
|
|
|
|
numtics += netbuffer[k++];
|
|
|
|
|
|
|
|
fprintf (debugfile,"%i/%i send %i = (%i + %i, R %i) [%3i]",
|
|
|
|
gametic, maketic,
|
|
|
|
node,
|
|
|
|
ExpandTics(netbuffer[1]),
|
|
|
|
numtics, realretrans, len);
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
2006-09-14 00:02:31 +00:00
|
|
|
fprintf (debugfile, "%c%2x", i==k?'|':' ', ((BYTE *)netbuffer)[i]);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
fprintf (debugfile, " [[ ");
|
2006-05-11 04:00:58 +00:00
|
|
|
for (i = 0; i < doomcom.numnodes; ++i)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (nodeingame[i])
|
|
|
|
{
|
|
|
|
fprintf (debugfile, "%d ", nettics[i]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf (debugfile, "--- ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf (debugfile, "]]\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (node == 0)
|
|
|
|
{
|
|
|
|
memcpy (reboundstore, netbuffer, len);
|
|
|
|
reboundpacket = len;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (demoplayback)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!netgame)
|
|
|
|
I_Error ("Tried to transmit to another node");
|
|
|
|
|
|
|
|
#if SIMULATEERRORS
|
|
|
|
if (rand() < SIMULATEERRORS)
|
|
|
|
{
|
|
|
|
if (debugfile)
|
|
|
|
fprintf (debugfile, "Drop!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
doomcom.command = CMD_SEND;
|
|
|
|
doomcom.remotenode = node;
|
|
|
|
doomcom.datalength = len;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2014-08-26 10:31:42 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
if (net_fakelatency / 2 > 0)
|
|
|
|
{
|
|
|
|
PacketStore store;
|
|
|
|
store.message = doomcom;
|
|
|
|
store.timer = I_GetTime(false) + ((net_fakelatency / 2) / (1000 / TICRATE));
|
|
|
|
OutBuffer.Push(store);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
I_NetCmd();
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < OutBuffer.Size(); i++)
|
|
|
|
{
|
|
|
|
if (OutBuffer[i].timer <= I_GetTime(false))
|
|
|
|
{
|
|
|
|
doomcom = OutBuffer[i].message;
|
|
|
|
I_NetCmd();
|
|
|
|
OutBuffer.Delete(i);
|
|
|
|
i = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
I_NetCmd();
|
|
|
|
#endif
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// HGetPacket
|
|
|
|
// Returns false if no packet is waiting
|
|
|
|
//
|
2006-09-14 00:02:31 +00:00
|
|
|
bool HGetPacket (void)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (reboundpacket)
|
|
|
|
{
|
|
|
|
memcpy (netbuffer, reboundstore, reboundpacket);
|
2006-05-11 04:00:58 +00:00
|
|
|
doomcom.remotenode = 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
reboundpacket = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!netgame)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (demoplayback)
|
|
|
|
return false;
|
2014-08-26 10:31:42 +00:00
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
doomcom.command = CMD_GET;
|
2006-02-24 04:48:15 +00:00
|
|
|
I_NetCmd ();
|
2014-08-26 10:31:42 +00:00
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
if (net_fakelatency / 2 > 0 && doomcom.remotenode != -1)
|
|
|
|
{
|
|
|
|
PacketStore store;
|
|
|
|
store.message = doomcom;
|
|
|
|
store.timer = I_GetTime(false) + ((net_fakelatency / 2) / (1000 / TICRATE));
|
|
|
|
InBuffer.Push(store);
|
|
|
|
doomcom.remotenode = -1;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
if (doomcom.remotenode == -1)
|
2014-08-26 10:31:42 +00:00
|
|
|
{
|
|
|
|
bool gotmessage = false;
|
|
|
|
for (unsigned int i = 0; i < InBuffer.Size(); i++)
|
|
|
|
{
|
|
|
|
if (InBuffer[i].timer <= I_GetTime(false))
|
|
|
|
{
|
|
|
|
doomcom = InBuffer[i].message;
|
|
|
|
InBuffer.Delete(i);
|
|
|
|
gotmessage = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!gotmessage)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (doomcom.remotenode == -1)
|
|
|
|
{
|
2006-02-24 04:48:15 +00:00
|
|
|
return false;
|
2014-08-26 10:31:42 +00:00
|
|
|
}
|
|
|
|
#endif
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (debugfile)
|
|
|
|
{
|
|
|
|
int i, k, realretrans;
|
|
|
|
|
|
|
|
if (netbuffer[0] & NCMD_SETUP)
|
|
|
|
{
|
2006-05-11 04:00:58 +00:00
|
|
|
fprintf (debugfile,"%i/%i get %i = SETUP [%3i]", gametic, maketic, doomcom.remotenode, doomcom.datalength);
|
|
|
|
for (i = 0; i < doomcom.datalength; i++)
|
2006-09-14 00:02:31 +00:00
|
|
|
fprintf (debugfile, " %2x", ((BYTE *)netbuffer)[i]);
|
2006-02-24 04:48:15 +00:00
|
|
|
fprintf (debugfile, "\n");
|
|
|
|
}
|
|
|
|
else if (netbuffer[0] & NCMD_EXIT)
|
|
|
|
{
|
2006-05-11 04:00:58 +00:00
|
|
|
fprintf (debugfile,"%i/%i get %i = EXIT [%3i]", gametic, maketic, doomcom.remotenode, doomcom.datalength);
|
|
|
|
for (i = 0; i < doomcom.datalength; i++)
|
2006-09-14 00:02:31 +00:00
|
|
|
fprintf (debugfile, " %2x", ((BYTE *)netbuffer)[i]);
|
2006-02-24 04:48:15 +00:00
|
|
|
fprintf (debugfile, "\n");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
k = 2;
|
|
|
|
|
|
|
|
if (NetMode == NET_PacketServer &&
|
2006-05-11 04:00:58 +00:00
|
|
|
doomcom.remotenode == nodeforplayer[Net_Arbitrator])
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (netbuffer[0] & NCMD_RETRANSMIT)
|
|
|
|
realretrans = ExpandTics (netbuffer[k++]);
|
|
|
|
else
|
|
|
|
realretrans = -1;
|
|
|
|
|
|
|
|
int numtics = netbuffer[0] & 3;
|
|
|
|
if (numtics == 3)
|
|
|
|
numtics += netbuffer[k++];
|
|
|
|
|
|
|
|
fprintf (debugfile,"%i/%i get %i = (%i + %i, R %i) [%3i]",
|
|
|
|
gametic, maketic,
|
2006-05-11 04:00:58 +00:00
|
|
|
doomcom.remotenode,
|
2006-02-24 04:48:15 +00:00
|
|
|
ExpandTics(netbuffer[1]),
|
2006-05-11 04:00:58 +00:00
|
|
|
numtics, realretrans, doomcom.datalength);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
for (i = 0; i < doomcom.datalength; i++)
|
2006-09-14 00:02:31 +00:00
|
|
|
fprintf (debugfile, "%c%2x", i==k?'|':' ', ((BYTE *)netbuffer)[i]);
|
2006-02-24 04:48:15 +00:00
|
|
|
if (numtics)
|
|
|
|
fprintf (debugfile, " <<%4x>>\n",
|
2006-05-11 04:00:58 +00:00
|
|
|
consistancy[playerfornode[doomcom.remotenode]][nettics[doomcom.remotenode]%BACKUPTICS] & 0xFFFF);
|
2006-02-24 04:48:15 +00:00
|
|
|
else
|
|
|
|
fprintf (debugfile, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
if (doomcom.datalength != NetbufferSize ())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2014-08-16 09:15:39 +00:00
|
|
|
Printf("Bad packet length %i (calculated %i)\n",
|
|
|
|
doomcom.datalength, NetbufferSize());
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (debugfile)
|
|
|
|
fprintf (debugfile,"---bad packet length %i (calculated %i)\n",
|
2006-05-11 04:00:58 +00:00
|
|
|
doomcom.datalength, NetbufferSize());
|
2006-02-24 04:48:15 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerIsGone (int netnode, int netconsole)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2014-12-23 09:20:39 +00:00
|
|
|
if (nodeingame[netnode])
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2014-12-23 09:20:39 +00:00
|
|
|
for (i = netnode + 1; i < doomcom.numnodes; ++i)
|
|
|
|
{
|
|
|
|
if (nodeingame[i])
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == doomcom.numnodes)
|
|
|
|
{
|
|
|
|
doomcom.numnodes = netnode;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2014-12-23 09:20:39 +00:00
|
|
|
if (playeringame[netconsole])
|
|
|
|
{
|
|
|
|
players[netconsole].playerstate = PST_GONE;
|
|
|
|
}
|
|
|
|
nodeingame[netnode] = false;
|
|
|
|
nodejustleft[netnode] = false;
|
|
|
|
}
|
|
|
|
else if (nodejustleft[netnode]) // Packet Server
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2014-12-23 09:20:39 +00:00
|
|
|
if (netnode + 1 == doomcom.numnodes)
|
|
|
|
{
|
|
|
|
doomcom.numnodes = netnode;
|
|
|
|
}
|
|
|
|
if (playeringame[netconsole])
|
|
|
|
{
|
|
|
|
players[netconsole].playerstate = PST_GONE;
|
|
|
|
}
|
|
|
|
nodejustleft[netnode] = false;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2014-12-23 09:20:39 +00:00
|
|
|
else return;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (netconsole == Net_Arbitrator)
|
|
|
|
{
|
|
|
|
// Pick a new network arbitrator
|
|
|
|
for (int i = 0; i < MAXPLAYERS; i++)
|
|
|
|
{
|
2014-10-14 18:57:11 +00:00
|
|
|
if (i != netconsole && playeringame[i] && players[i].Bot == NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
Net_Arbitrator = i;
|
2008-02-16 15:02:52 +00:00
|
|
|
players[i].settings_controller = true;
|
2014-10-05 05:04:11 +00:00
|
|
|
Printf("%s is the new arbitrator\n", players[i].userinfo.GetName());
|
2006-02-24 04:48:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-10-05 05:04:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (debugfile && NetMode == NET_PacketServer)
|
|
|
|
{
|
|
|
|
if (Net_Arbitrator == consoleplayer)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2014-10-05 05:04:11 +00:00
|
|
|
fprintf(debugfile, "I am the new master!\n");
|
|
|
|
}
|
|
|
|
else
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2014-10-05 05:04:11 +00:00
|
|
|
fprintf(debugfile, "Node %d is the new master!\n", nodeforplayer[Net_Arbitrator]);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (demorecording)
|
|
|
|
{
|
|
|
|
G_CheckDemoStatus ();
|
|
|
|
|
|
|
|
//WriteByte (DEM_DROPPLAYER, &demo_p);
|
2006-09-14 00:02:31 +00:00
|
|
|
//WriteByte ((BYTE)netconsole, &demo_p);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// GetPackets
|
|
|
|
//
|
|
|
|
|
|
|
|
void GetPackets (void)
|
|
|
|
{
|
|
|
|
int netconsole;
|
|
|
|
int netnode;
|
|
|
|
int realend;
|
|
|
|
int realstart;
|
|
|
|
int numtics;
|
|
|
|
int retransmitfrom;
|
|
|
|
int k;
|
|
|
|
BYTE playerbytes[MAXNETNODES];
|
|
|
|
int numplayers;
|
|
|
|
|
|
|
|
while ( HGetPacket() )
|
|
|
|
{
|
|
|
|
if (netbuffer[0] & NCMD_SETUP)
|
|
|
|
{
|
|
|
|
if (consoleplayer == Net_Arbitrator)
|
|
|
|
{
|
|
|
|
// This player apparantly doesn't realise the game has started
|
|
|
|
netbuffer[0] = NCMD_SETUP+3;
|
2006-05-11 04:00:58 +00:00
|
|
|
HSendPacket (doomcom.remotenode, 1);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
continue; // extra setup packet
|
|
|
|
}
|
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
netnode = doomcom.remotenode;
|
2006-02-24 04:48:15 +00:00
|
|
|
netconsole = playerfornode[netnode] & ~PL_DRONE;
|
|
|
|
|
2007-01-22 23:50:09 +00:00
|
|
|
// [RH] Get "ping" times - totally useless, since it's bound to the frequency
|
|
|
|
// packets go out at.
|
2006-02-24 04:48:15 +00:00
|
|
|
lastrecvtime[netconsole] = currrecvtime[netconsole];
|
|
|
|
currrecvtime[netconsole] = I_MSTime ();
|
2007-01-22 23:50:09 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// check for exiting the game
|
|
|
|
if (netbuffer[0] & NCMD_EXIT)
|
|
|
|
{
|
|
|
|
if (!nodeingame[netnode])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (NetMode != NET_PacketServer || netconsole == Net_Arbitrator)
|
|
|
|
{
|
|
|
|
PlayerIsGone (netnode, netconsole);
|
|
|
|
if (NetMode == NET_PacketServer)
|
|
|
|
{
|
|
|
|
BYTE *foo = &netbuffer[2];
|
|
|
|
for (int i = 0; i < MAXPLAYERS; ++i)
|
|
|
|
{
|
|
|
|
if (playeringame[i])
|
|
|
|
{
|
|
|
|
int resend = ReadLong (&foo);
|
|
|
|
if (i != consoleplayer)
|
|
|
|
{
|
|
|
|
resendto[nodeforplayer[i]] = resend;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nodeingame[netnode] = false;
|
|
|
|
nodejustleft[netnode] = true;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
k = 2;
|
|
|
|
|
|
|
|
if (NetMode == NET_PacketServer &&
|
|
|
|
netconsole == Net_Arbitrator &&
|
|
|
|
netconsole != consoleplayer)
|
|
|
|
{
|
|
|
|
mastertics = ExpandTics (netbuffer[k++]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (netbuffer[0] & NCMD_RETRANSMIT)
|
|
|
|
{
|
|
|
|
retransmitfrom = netbuffer[k++];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
retransmitfrom = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
numtics = (netbuffer[0] & NCMD_XTICS);
|
|
|
|
if (numtics == 3)
|
|
|
|
{
|
|
|
|
numtics += netbuffer[k++];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (netbuffer[0] & NCMD_QUITTERS)
|
|
|
|
{
|
|
|
|
numplayers = netbuffer[k++];
|
|
|
|
for (int i = 0; i < numplayers; ++i)
|
|
|
|
{
|
|
|
|
PlayerIsGone (nodeforplayer[netbuffer[k]], netbuffer[k]);
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-18 09:08:17 +00:00
|
|
|
// Pull current network delay from node
|
2014-08-19 10:30:33 +00:00
|
|
|
netdelay[netnode][(nettics[netnode]+1) % BACKUPTICS] = netbuffer[k++];
|
2014-08-16 09:15:39 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
playerbytes[0] = netconsole;
|
|
|
|
if (netbuffer[0] & NCMD_MULTI)
|
|
|
|
{
|
|
|
|
numplayers = netbuffer[k++];
|
|
|
|
memcpy (playerbytes+1, &netbuffer[k], numplayers - 1);
|
|
|
|
k += numplayers - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
numplayers = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// to save bytes, only the low byte of tic numbers are sent
|
|
|
|
// Figure out what the rest of the bytes are
|
|
|
|
realstart = ExpandTics (netbuffer[1]);
|
|
|
|
realend = (realstart + numtics);
|
|
|
|
|
|
|
|
nodeforplayer[netconsole] = netnode;
|
|
|
|
|
|
|
|
// check for retransmit request
|
|
|
|
if (resendcount[netnode] <= 0 && (netbuffer[0] & NCMD_RETRANSMIT))
|
|
|
|
{
|
|
|
|
resendto[netnode] = ExpandTics (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, 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 to %i)\n",
|
|
|
|
netnode, nettics[netnode], realstart);
|
|
|
|
remoteresend[netnode] = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// update command store from the packet
|
|
|
|
{
|
2006-09-14 00:02:31 +00:00
|
|
|
BYTE *start;
|
2006-02-24 04:48:15 +00:00
|
|
|
int i, tics;
|
|
|
|
remoteresend[netnode] = false;
|
|
|
|
|
|
|
|
start = &netbuffer[k];
|
|
|
|
|
|
|
|
for (i = 0; i < numplayers; ++i)
|
|
|
|
{
|
2014-11-08 17:38:09 +00:00
|
|
|
int node = nodeforplayer[playerbytes[i]];
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
SkipTicCmd (&start, nettics[node] - realstart);
|
|
|
|
for (tics = nettics[node]; tics < realend; tics++)
|
|
|
|
ReadTicCmd (&start, playerbytes[i], tics);
|
|
|
|
|
2014-11-08 17:38:09 +00:00
|
|
|
nettics[nodeforplayer[playerbytes[i]]] = realend;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// NetUpdate
|
|
|
|
// Builds ticcmds for console player,
|
|
|
|
// sends out a packet
|
|
|
|
//
|
|
|
|
int gametime;
|
|
|
|
|
|
|
|
void NetUpdate (void)
|
|
|
|
{
|
|
|
|
int lowtic;
|
|
|
|
int nowtime;
|
|
|
|
int newtics;
|
|
|
|
int i,j;
|
|
|
|
int realstart;
|
2006-09-14 00:02:31 +00:00
|
|
|
BYTE *cmddata;
|
2006-02-24 04:48:15 +00:00
|
|
|
bool resendOnly;
|
|
|
|
|
2008-03-12 02:56:11 +00:00
|
|
|
GC::CheckGC();
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (ticdup == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check time
|
|
|
|
nowtime = I_GetTime (false);
|
|
|
|
newtics = nowtime - gametime;
|
|
|
|
gametime = nowtime;
|
|
|
|
|
2015-02-05 09:43:42 +00:00
|
|
|
if (newtics <= 0) // nothing new to update
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
GetPackets ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (skiptics <= newtics)
|
|
|
|
{
|
|
|
|
newtics -= skiptics;
|
|
|
|
skiptics = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
skiptics -= newtics;
|
|
|
|
newtics = 0;
|
|
|
|
}
|
|
|
|
|
2014-11-08 17:38:09 +00:00
|
|
|
// build new ticcmds for console player
|
2006-02-24 04:48:15 +00:00
|
|
|
for (i = 0; i < newtics; i++)
|
|
|
|
{
|
|
|
|
I_StartTic ();
|
|
|
|
D_ProcessEvents ();
|
|
|
|
if ((maketic - gametic) / ticdup >= BACKUPTICS/2-1)
|
|
|
|
break; // can't hold any more
|
|
|
|
|
|
|
|
//Printf ("mk:%i ",maketic);
|
|
|
|
G_BuildTiccmd (&localcmds[maketic % LOCALCMDTICS]);
|
|
|
|
maketic++;
|
|
|
|
|
|
|
|
if (ticdup == 1 || maketic == 0)
|
|
|
|
{
|
|
|
|
Net_NewMakeTic ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Once ticdup tics have been collected, average their movements
|
|
|
|
// and combine their buttons, since they will all be sent as a
|
|
|
|
// single tic that gets duplicated ticdup times. Even with ticdup,
|
|
|
|
// tics are still collected at the normal rate so that, with the
|
|
|
|
// help of prediction, the game seems as responsive as normal.
|
|
|
|
if (maketic % ticdup != 0)
|
|
|
|
{
|
|
|
|
int mod = maketic - maketic % ticdup;
|
|
|
|
int j;
|
|
|
|
|
|
|
|
// Update the buttons for all tics in this ticdup set as soon as
|
|
|
|
// possible so that the prediction shows jumping as correctly as
|
|
|
|
// possible. (If you press +jump in the middle of a ticdup set,
|
|
|
|
// the jump will actually begin at the beginning of the set, not
|
|
|
|
// in the middle.)
|
|
|
|
for (j = maketic-2; j >= mod; --j)
|
|
|
|
{
|
|
|
|
localcmds[j % LOCALCMDTICS].ucmd.buttons |=
|
|
|
|
localcmds[(j + 1) % LOCALCMDTICS].ucmd.buttons;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Average the ticcmds between these tics to get the
|
|
|
|
// movement that is actually sent across the network. We
|
|
|
|
// need to update them in all the localcmds slots that
|
|
|
|
// are dupped so that prediction works properly.
|
|
|
|
int mod = maketic - ticdup;
|
|
|
|
int modp, j;
|
|
|
|
|
|
|
|
int pitch = 0;
|
|
|
|
int yaw = 0;
|
|
|
|
int roll = 0;
|
|
|
|
int forwardmove = 0;
|
|
|
|
int sidemove = 0;
|
|
|
|
int upmove = 0;
|
|
|
|
|
|
|
|
for (j = 0; j < ticdup; ++j)
|
|
|
|
{
|
|
|
|
modp = (mod + j) % LOCALCMDTICS;
|
|
|
|
pitch += localcmds[modp].ucmd.pitch;
|
|
|
|
yaw += localcmds[modp].ucmd.yaw;
|
|
|
|
roll += localcmds[modp].ucmd.roll;
|
|
|
|
forwardmove += localcmds[modp].ucmd.forwardmove;
|
|
|
|
sidemove += localcmds[modp].ucmd.sidemove;
|
|
|
|
upmove += localcmds[modp].ucmd.upmove;
|
|
|
|
}
|
|
|
|
|
|
|
|
pitch /= ticdup;
|
|
|
|
yaw /= ticdup;
|
|
|
|
roll /= ticdup;
|
|
|
|
forwardmove /= ticdup;
|
|
|
|
sidemove /= ticdup;
|
|
|
|
upmove /= ticdup;
|
|
|
|
|
|
|
|
for (j = 0; j < ticdup; ++j)
|
|
|
|
{
|
|
|
|
modp = (mod + j) % LOCALCMDTICS;
|
|
|
|
localcmds[modp].ucmd.pitch = pitch;
|
|
|
|
localcmds[modp].ucmd.yaw = yaw;
|
|
|
|
localcmds[modp].ucmd.roll = roll;
|
|
|
|
localcmds[modp].ucmd.forwardmove = forwardmove;
|
|
|
|
localcmds[modp].ucmd.sidemove = sidemove;
|
|
|
|
localcmds[modp].ucmd.upmove = upmove;
|
|
|
|
}
|
|
|
|
|
|
|
|
Net_NewMakeTic ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (singletics)
|
|
|
|
return; // singletic update is synchronous
|
|
|
|
|
2014-05-05 10:47:48 +00:00
|
|
|
if (demoplayback)
|
|
|
|
{
|
2014-05-16 12:35:27 +00:00
|
|
|
resendto[0] = nettics[0] = (maketic / ticdup);
|
2014-05-05 10:47:48 +00:00
|
|
|
return; // Don't touch netcmd data while playing a demo, as it'll already exist.
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// If maketic didn't cross a ticdup boundary, only send packets
|
|
|
|
// to players waiting for resends.
|
|
|
|
resendOnly = (maketic / ticdup) == (maketic - i) / ticdup;
|
|
|
|
|
|
|
|
// send the packet to the other nodes
|
|
|
|
int count = 1;
|
|
|
|
int quitcount = 0;
|
|
|
|
|
|
|
|
if (consoleplayer == Net_Arbitrator)
|
|
|
|
{
|
2014-12-22 20:48:27 +00:00
|
|
|
if (NetMode == NET_PacketServer)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2014-12-22 20:48:27 +00:00
|
|
|
for (j = 0; j < MAXPLAYERS; j++)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2014-12-22 20:48:27 +00:00
|
|
|
if (playeringame[j] && players[j].Bot == NULL)
|
|
|
|
{
|
|
|
|
count++;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// The loop above added the local player to the count a second time,
|
|
|
|
// and it also added the player being sent the packet to the count.
|
|
|
|
count -= 2;
|
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
for (j = 0; j < doomcom.numnodes; ++j)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (nodejustleft[j])
|
|
|
|
{
|
|
|
|
if (count == 0)
|
|
|
|
{
|
|
|
|
PlayerIsGone (j, playerfornode[j]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
quitcount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count == 0)
|
|
|
|
{
|
|
|
|
count = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
for (i = 0; i < doomcom.numnodes; i++)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
BYTE playerbytes[MAXPLAYERS];
|
|
|
|
|
|
|
|
if (!nodeingame[i])
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (NetMode == NET_PacketServer &&
|
|
|
|
consoleplayer != Net_Arbitrator &&
|
|
|
|
i != nodeforplayer[Net_Arbitrator] &&
|
|
|
|
i != 0)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (resendOnly && resendcount[i] <= 0 && !remoteresend[i] && nettics[i])
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int numtics;
|
|
|
|
int k;
|
|
|
|
|
|
|
|
lowtic = maketic / ticdup;
|
|
|
|
|
|
|
|
netbuffer[0] = 0;
|
|
|
|
netbuffer[1] = realstart = resendto[i];
|
|
|
|
k = 2;
|
|
|
|
|
|
|
|
if (NetMode == NET_PacketServer &&
|
|
|
|
consoleplayer == Net_Arbitrator &&
|
|
|
|
i != 0)
|
|
|
|
{
|
2006-05-11 04:00:58 +00:00
|
|
|
for (j = 1; j < doomcom.numnodes; ++j)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (nodeingame[j] && nettics[j] < lowtic && j != i)
|
|
|
|
{
|
|
|
|
lowtic = nettics[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
netbuffer[k++] = lowtic;
|
|
|
|
}
|
|
|
|
|
2014-08-26 10:31:42 +00:00
|
|
|
numtics = MAX(0, lowtic - realstart);
|
2006-02-24 04:48:15 +00:00
|
|
|
if (numtics > BACKUPTICS)
|
|
|
|
I_Error ("NetUpdate: Node %d missed too many tics", i);
|
|
|
|
|
2014-08-18 09:46:48 +00:00
|
|
|
switch (net_extratic)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
default:
|
2014-08-21 04:31:29 +00:00
|
|
|
resendto[i] = lowtic; break;
|
2014-08-18 09:46:48 +00:00
|
|
|
case 1: resendto[i] = MAX(0, lowtic - 1); break;
|
2014-08-18 10:55:13 +00:00
|
|
|
case 2: resendto[i] = nettics[i]; break;
|
2014-08-18 09:46:48 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (numtics == 0 && resendOnly && !remoteresend[i] && nettics[i])
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (remoteresend[i])
|
|
|
|
{
|
|
|
|
netbuffer[0] |= NCMD_RETRANSMIT;
|
|
|
|
netbuffer[k++] = nettics[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (numtics < 3)
|
|
|
|
{
|
|
|
|
netbuffer[0] |= numtics;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
netbuffer[0] |= NCMD_XTICS;
|
|
|
|
netbuffer[k++] = numtics - 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (quitcount > 0)
|
|
|
|
{
|
|
|
|
netbuffer[0] |= NCMD_QUITTERS;
|
|
|
|
netbuffer[k++] = quitcount;
|
2006-05-11 04:00:58 +00:00
|
|
|
for (int l = 0; l < doomcom.numnodes; ++l)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (nodejustleft[l])
|
|
|
|
{
|
|
|
|
netbuffer[k++] = playerfornode[l];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-18 09:08:17 +00:00
|
|
|
// Send current network delay
|
|
|
|
// The number of tics we just made should be removed from the count.
|
2014-08-18 09:46:48 +00:00
|
|
|
netbuffer[k++] = ((maketic - newtics - gametic) / ticdup);
|
2014-08-16 09:15:39 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (numtics > 0)
|
|
|
|
{
|
|
|
|
int l;
|
|
|
|
|
|
|
|
if (count > 1 && i != 0 && consoleplayer == Net_Arbitrator)
|
|
|
|
{
|
|
|
|
netbuffer[0] |= NCMD_MULTI;
|
|
|
|
netbuffer[k++] = count;
|
|
|
|
|
2014-12-22 20:48:27 +00:00
|
|
|
if (NetMode == NET_PacketServer)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2014-12-22 20:48:27 +00:00
|
|
|
for (l = 1, j = 0; j < MAXPLAYERS; j++)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2014-12-22 20:48:27 +00:00
|
|
|
if (playeringame[j] && players[j].Bot == NULL && j != playerfornode[i] && j != consoleplayer)
|
|
|
|
{
|
|
|
|
playerbytes[l++] = j;
|
|
|
|
netbuffer[k++] = j;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cmddata = &netbuffer[k];
|
|
|
|
|
|
|
|
for (l = 0; l < count; ++l)
|
|
|
|
{
|
|
|
|
for (j = 0; j < numtics; j++)
|
|
|
|
{
|
|
|
|
int start = realstart + j, prev = start - 1;
|
|
|
|
int localstart, localprev;
|
|
|
|
|
|
|
|
localstart = (start * ticdup) % LOCALCMDTICS;
|
|
|
|
localprev = (prev * ticdup) % LOCALCMDTICS;
|
|
|
|
start %= BACKUPTICS;
|
|
|
|
prev %= BACKUPTICS;
|
|
|
|
|
|
|
|
// The local player has their tics sent first, followed by
|
2014-11-08 17:38:09 +00:00
|
|
|
// the other players.
|
2006-02-24 04:48:15 +00:00
|
|
|
if (l == 0)
|
|
|
|
{
|
|
|
|
WriteWord (localcmds[localstart].consistancy, &cmddata);
|
|
|
|
// [RH] Write out special "ticcmds" before real ticcmd
|
|
|
|
if (specials.used[start])
|
|
|
|
{
|
|
|
|
memcpy (cmddata, specials.streams[start], specials.used[start]);
|
|
|
|
cmddata += specials.used[start];
|
|
|
|
}
|
|
|
|
WriteUserCmdMessage (&localcmds[localstart].ucmd,
|
|
|
|
localprev >= 0 ? &localcmds[localprev].ucmd : NULL, &cmddata);
|
|
|
|
}
|
|
|
|
else if (i != 0)
|
|
|
|
{
|
2014-11-08 17:38:09 +00:00
|
|
|
int len;
|
|
|
|
BYTE *spec;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2014-11-08 17:38:09 +00:00
|
|
|
WriteWord (netcmds[playerbytes[l]][start].consistancy, &cmddata);
|
|
|
|
spec = NetSpecs[playerbytes[l]][start].GetData (&len);
|
|
|
|
if (spec != NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2014-11-08 17:38:09 +00:00
|
|
|
memcpy (cmddata, spec, len);
|
|
|
|
cmddata += len;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WriteUserCmdMessage (&netcmds[playerbytes[l]][start].ucmd,
|
|
|
|
prev >= 0 ? &netcmds[playerbytes[l]][prev].ucmd : NULL, &cmddata);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-05-15 10:39:40 +00:00
|
|
|
HSendPacket (i, int(cmddata - netbuffer));
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
HSendPacket (i, k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// listen for other packets
|
|
|
|
GetPackets ();
|
2014-07-14 10:26:40 +00:00
|
|
|
|
2014-07-28 23:06:02 +00:00
|
|
|
if (!resendOnly)
|
2014-07-14 10:26:40 +00:00
|
|
|
{
|
|
|
|
// ideally nettics[0] should be 1 - 3 tics above lowtic
|
|
|
|
// if we are consistantly slower, speed up time
|
|
|
|
|
|
|
|
// [RH] I had erroneously assumed frameskip[] had 4 entries
|
|
|
|
// because there were 4 players, but that's not the case at
|
|
|
|
// all. The game is comparing the lag behind the master for
|
|
|
|
// four runs of TryRunTics. If our tic count is ahead of the
|
|
|
|
// master all 4 times, the next run of NetUpdate will not
|
|
|
|
// process any new input. If we have less input than the
|
|
|
|
// master, the next run of NetUpdate will process extra tics
|
|
|
|
// (because gametime gets decremented here).
|
|
|
|
|
|
|
|
// the key player does not adapt
|
|
|
|
if (consoleplayer != Net_Arbitrator)
|
|
|
|
{
|
|
|
|
// I'm not sure about this when using a packet server, because
|
|
|
|
// if left unmodified from the P2P version, it can make the game
|
|
|
|
// very jerky. The way I have it written right now basically means
|
|
|
|
// that it won't adapt. Fortunately, player prediction helps
|
|
|
|
// alleviate the lag somewhat.
|
|
|
|
|
2014-08-16 09:15:39 +00:00
|
|
|
if (NetMode == NET_PeerToPeer)
|
2014-07-14 10:26:40 +00:00
|
|
|
{
|
2014-08-26 10:31:42 +00:00
|
|
|
int totalavg = 0;
|
2014-08-18 09:08:17 +00:00
|
|
|
if (net_ticbalance)
|
2014-08-19 10:30:33 +00:00
|
|
|
{
|
2014-09-26 04:11:52 +00:00
|
|
|
// Try to guess ahead the time it takes to send responses to the slowest node
|
2014-09-26 03:37:14 +00:00
|
|
|
int nodeavg = 0, arbavg = 0;
|
2014-08-26 10:31:42 +00:00
|
|
|
|
2014-09-26 03:37:14 +00:00
|
|
|
for (j = 0; j < BACKUPTICS; j++)
|
|
|
|
{
|
|
|
|
arbavg += netdelay[nodeforplayer[Net_Arbitrator]][j];
|
|
|
|
nodeavg += netdelay[0][j];
|
2014-08-26 10:31:42 +00:00
|
|
|
}
|
2014-09-26 03:37:14 +00:00
|
|
|
arbavg /= BACKUPTICS;
|
|
|
|
nodeavg /= BACKUPTICS;
|
2014-08-26 10:31:42 +00:00
|
|
|
|
2014-09-26 04:11:52 +00:00
|
|
|
// We shouldn't adapt if we are already the arbitrator isn't what we are waiting for, otherwise it just adds more latency
|
2014-09-26 03:37:14 +00:00
|
|
|
if (arbavg > nodeavg)
|
2014-08-26 10:31:42 +00:00
|
|
|
{
|
2014-09-26 03:37:14 +00:00
|
|
|
lastaverage = totalavg = ((arbavg + nodeavg) / 2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-09-26 04:11:52 +00:00
|
|
|
// Allow room to guess two tics ahead
|
2014-09-26 03:37:14 +00:00
|
|
|
if (nodeavg > (arbavg + 2) && lastaverage > 0)
|
|
|
|
lastaverage--;
|
|
|
|
totalavg = lastaverage;
|
2014-08-19 10:30:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-26 10:31:42 +00:00
|
|
|
mastertics = nettics[nodeforplayer[Net_Arbitrator]] + totalavg;
|
2014-07-14 10:26:40 +00:00
|
|
|
}
|
|
|
|
if (nettics[0] <= mastertics)
|
|
|
|
{
|
|
|
|
gametime--;
|
|
|
|
if (debugfile) fprintf(debugfile, "-");
|
|
|
|
}
|
|
|
|
if (NetMode != NET_PacketServer)
|
|
|
|
{
|
|
|
|
frameskip[(maketic / ticdup) & 3] = (oldnettics > mastertics);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
frameskip[(maketic / ticdup) & 3] = (oldnettics - mastertics) > 3;
|
|
|
|
}
|
|
|
|
if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
|
|
|
|
{
|
|
|
|
skiptics = 1;
|
|
|
|
if (debugfile) fprintf(debugfile, "+");
|
|
|
|
}
|
|
|
|
oldnettics = nettics[0];
|
|
|
|
}
|
2014-07-28 23:06:02 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// D_ArbitrateNetStart
|
|
|
|
//
|
|
|
|
// User info packets look like this:
|
|
|
|
//
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
// 0 One byte set to NCMD_SETUP or NCMD_SETUP+1; if NCMD_SETUP+1, omit byte 9
|
2006-02-24 04:48:15 +00:00
|
|
|
// 1 One byte for the player's number
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
//2-4 Three bytes for the game version (255,high byte,low byte)
|
|
|
|
//5-8 A bit mask for each player the sender knows about
|
|
|
|
// 9 The high bit is set if the sender got the game info
|
|
|
|
// 10 A stream of bytes with the user info
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
// The guests always send NCMD_SETUP packets, and the host always
|
|
|
|
// sends NCMD_SETUP+1 packets.
|
|
|
|
//
|
|
|
|
// Game info packets look like this:
|
|
|
|
//
|
|
|
|
// 0 One byte set to NCMD_SETUP+2
|
|
|
|
// 1 One byte for ticdup setting
|
2014-08-18 09:46:48 +00:00
|
|
|
// 2 One byte for NetMode setting
|
|
|
|
// 3 String with starting map's name
|
2006-02-24 04:48:15 +00:00
|
|
|
// . Four bytes for the RNG seed
|
|
|
|
// . Stream containing remaining game info
|
|
|
|
//
|
|
|
|
// Finished packet looks like this:
|
|
|
|
//
|
|
|
|
// 0 One byte set to NCMD_SETUP+3
|
|
|
|
//
|
|
|
|
// Each machine sends user info packets to the host. The host sends user
|
|
|
|
// info packets back to the other machines as well as game info packets.
|
|
|
|
// Negotiation is done when all the guests have reported to the host that
|
|
|
|
// they know about the other nodes.
|
|
|
|
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
struct ArbitrateData
|
|
|
|
{
|
|
|
|
DWORD playersdetected[MAXNETNODES];
|
|
|
|
BYTE gotsetup[MAXNETNODES];
|
|
|
|
};
|
|
|
|
|
|
|
|
bool DoArbitrate (void *userdata)
|
|
|
|
{
|
|
|
|
ArbitrateData *data = (ArbitrateData *)userdata;
|
|
|
|
char *s;
|
|
|
|
BYTE *stream;
|
|
|
|
int version;
|
|
|
|
int node;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
while (HGetPacket ())
|
|
|
|
{
|
|
|
|
if (netbuffer[0] == NCMD_EXIT)
|
|
|
|
{
|
|
|
|
I_FatalError ("The game was aborted.");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (doomcom.remotenode == 0)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (netbuffer[0] == NCMD_SETUP || netbuffer[0] == NCMD_SETUP+1) // got user info
|
|
|
|
{
|
|
|
|
node = (netbuffer[0] == NCMD_SETUP) ? doomcom.remotenode : nodeforplayer[netbuffer[1]];
|
|
|
|
|
|
|
|
data->playersdetected[node] =
|
|
|
|
(netbuffer[5] << 24) | (netbuffer[6] << 16) | (netbuffer[7] << 8) | netbuffer[8];
|
|
|
|
|
|
|
|
if (netbuffer[0] == NCMD_SETUP)
|
|
|
|
{ // Sent to host
|
|
|
|
data->gotsetup[node] = netbuffer[9] & 0x80;
|
|
|
|
stream = &netbuffer[10];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // Sent from host
|
|
|
|
stream = &netbuffer[9];
|
|
|
|
}
|
|
|
|
|
2008-01-09 02:53:38 +00:00
|
|
|
D_ReadUserInfoStrings (netbuffer[1], &stream, false);
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
if (!nodeingame[node])
|
|
|
|
{
|
|
|
|
version = (netbuffer[2] << 16) | (netbuffer[3] << 8) | netbuffer[4];
|
|
|
|
if (version != (0xFF0000 | NETGAMEVERSION))
|
|
|
|
{
|
|
|
|
I_Error ("Different " GAMENAME " versions cannot play a net game");
|
|
|
|
}
|
|
|
|
|
|
|
|
playeringame[netbuffer[1]] = true;
|
|
|
|
nodeingame[node] = true;
|
|
|
|
|
2008-01-09 02:53:38 +00:00
|
|
|
data->playersdetected[0] |= 1 << netbuffer[1];
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
|
2007-03-06 01:33:18 +00:00
|
|
|
StartScreen->NetMessage ("Found %s (node %d, player %d)",
|
2013-05-12 18:27:03 +00:00
|
|
|
players[netbuffer[1]].userinfo.GetName(),
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
node, netbuffer[1]+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (netbuffer[0] == NCMD_SETUP+2) // got game info
|
|
|
|
{
|
|
|
|
data->gotsetup[0] = 0x80;
|
|
|
|
|
|
|
|
ticdup = doomcom.ticdup = netbuffer[1];
|
2014-08-18 09:46:48 +00:00
|
|
|
NetMode = netbuffer[2];
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
|
2014-08-18 09:46:48 +00:00
|
|
|
stream = &netbuffer[3];
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
s = ReadString (&stream);
|
2014-05-18 07:41:13 +00:00
|
|
|
startmap = s;
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
delete[] s;
|
|
|
|
rngseed = ReadLong (&stream);
|
|
|
|
C_ReadCVars (&stream);
|
|
|
|
}
|
|
|
|
else if (netbuffer[0] == NCMD_SETUP+3)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If everybody already knows everything, it's time to go
|
|
|
|
if (consoleplayer == Net_Arbitrator)
|
|
|
|
{
|
|
|
|
for (i = 0; i < doomcom.numnodes; ++i)
|
|
|
|
if (data->playersdetected[i] != DWORD(1 << doomcom.numnodes) - 1 || !data->gotsetup[i])
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (i == doomcom.numnodes)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
netbuffer[2] = 255;
|
|
|
|
netbuffer[3] = (NETGAMEVERSION >> 8) & 255;
|
|
|
|
netbuffer[4] = NETGAMEVERSION & 255;
|
|
|
|
netbuffer[5] = data->playersdetected[0] >> 24;
|
|
|
|
netbuffer[6] = data->playersdetected[0] >> 16;
|
|
|
|
netbuffer[7] = data->playersdetected[0] >> 8;
|
|
|
|
netbuffer[8] = data->playersdetected[0];
|
|
|
|
|
|
|
|
if (consoleplayer != Net_Arbitrator)
|
|
|
|
{ // Send user info for the local node
|
|
|
|
netbuffer[0] = NCMD_SETUP;
|
|
|
|
netbuffer[1] = consoleplayer;
|
|
|
|
netbuffer[9] = data->gotsetup[0];
|
|
|
|
stream = &netbuffer[10];
|
|
|
|
D_WriteUserInfoStrings (consoleplayer, &stream, true);
|
2009-05-15 10:39:40 +00:00
|
|
|
SendSetup (data->playersdetected, data->gotsetup, int(stream - netbuffer));
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // Send user info for all nodes
|
|
|
|
netbuffer[0] = NCMD_SETUP+1;
|
|
|
|
for (i = 1; i < doomcom.numnodes; ++i)
|
|
|
|
{
|
|
|
|
for (j = 0; j < doomcom.numnodes; ++j)
|
|
|
|
{
|
|
|
|
// Send info about player j to player i?
|
2008-01-09 02:53:38 +00:00
|
|
|
if ((data->playersdetected[0] & (1<<j)) && !(data->playersdetected[i] & (1<<j)))
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
{
|
|
|
|
netbuffer[1] = j;
|
|
|
|
stream = &netbuffer[9];
|
|
|
|
D_WriteUserInfoStrings (j, &stream, true);
|
2009-05-15 10:39:40 +00:00
|
|
|
HSendPacket (i, int(stream - netbuffer));
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we're the host, send the game info, too
|
|
|
|
if (consoleplayer == Net_Arbitrator)
|
|
|
|
{
|
|
|
|
netbuffer[0] = NCMD_SETUP+2;
|
2009-05-15 10:39:40 +00:00
|
|
|
netbuffer[1] = (BYTE)doomcom.ticdup;
|
2014-08-18 09:46:48 +00:00
|
|
|
netbuffer[2] = NetMode;
|
|
|
|
stream = &netbuffer[3];
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
WriteString (startmap, &stream);
|
|
|
|
WriteLong (rngseed, &stream);
|
|
|
|
C_WriteCVars (&stream, CVAR_SERVERINFO, true);
|
|
|
|
|
2009-05-15 10:39:40 +00:00
|
|
|
SendSetup (data->playersdetected, data->gotsetup, int(stream - netbuffer));
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
void D_ArbitrateNetStart (void)
|
|
|
|
{
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
ArbitrateData data;
|
|
|
|
int i;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// Return right away if we're just playing with ourselves.
|
2006-05-11 04:00:58 +00:00
|
|
|
if (doomcom.numnodes == 1)
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
autostart = true;
|
|
|
|
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
memset (data.playersdetected, 0, sizeof(data.playersdetected));
|
|
|
|
memset (data.gotsetup, 0, sizeof(data.gotsetup));
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2008-01-09 02:53:38 +00:00
|
|
|
// The arbitrator knows about himself, but the other players must
|
|
|
|
// be told about themselves, in case the host had to adjust their
|
|
|
|
// userinfo (e.g. assign them to a different team).
|
|
|
|
if (consoleplayer == Net_Arbitrator)
|
|
|
|
{
|
|
|
|
data.playersdetected[0] = 1 << consoleplayer;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
// Assign nodes to players. The local player is always node 0.
|
|
|
|
// If the local player is not the host, then the host is node 1.
|
|
|
|
// Any remaining players are assigned node numbers in the order
|
|
|
|
// they were detected.
|
2006-02-24 04:48:15 +00:00
|
|
|
playerfornode[0] = consoleplayer;
|
|
|
|
nodeforplayer[consoleplayer] = 0;
|
|
|
|
if (consoleplayer == Net_Arbitrator)
|
|
|
|
{
|
2006-05-11 04:00:58 +00:00
|
|
|
for (i = 1; i < doomcom.numnodes; ++i)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
playerfornode[i] = i;
|
|
|
|
nodeforplayer[i] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
playerfornode[1] = 0;
|
|
|
|
nodeforplayer[0] = 1;
|
2006-05-11 04:00:58 +00:00
|
|
|
for (i = 1; i < doomcom.numnodes; ++i)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (i < consoleplayer)
|
|
|
|
{
|
|
|
|
playerfornode[i+1] = i;
|
|
|
|
nodeforplayer[i] = i+1;
|
|
|
|
}
|
|
|
|
else if (i > consoleplayer)
|
|
|
|
{
|
|
|
|
playerfornode[i] = i;
|
|
|
|
nodeforplayer[i] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (consoleplayer == Net_Arbitrator)
|
|
|
|
{
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
data.gotsetup[0] = 0x80;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2007-03-06 01:33:18 +00:00
|
|
|
StartScreen->NetInit ("Exchanging game information", 1);
|
|
|
|
if (!StartScreen->NetLoop (DoArbitrate, &data))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
exit (0);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (consoleplayer == Net_Arbitrator)
|
|
|
|
{
|
|
|
|
netbuffer[0] = NCMD_SETUP+3;
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
SendSetup (data.playersdetected, data.gotsetup, 1);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (debugfile)
|
|
|
|
{
|
2006-05-11 04:00:58 +00:00
|
|
|
for (i = 0; i < doomcom.numnodes; ++i)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
fprintf (debugfile, "player %d is on node %d\n", i, nodeforplayer[i]);
|
|
|
|
}
|
|
|
|
}
|
2007-03-06 01:33:18 +00:00
|
|
|
StartScreen->NetDone();
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void SendSetup (DWORD playersdetected[MAXNETNODES], BYTE gotsetup[MAXNETNODES], int len)
|
|
|
|
{
|
|
|
|
if (consoleplayer != Net_Arbitrator)
|
|
|
|
{
|
|
|
|
if (playersdetected[1] & (1 << consoleplayer))
|
|
|
|
{
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
HSendPacket (1, 10);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
HSendPacket (1, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-05-11 04:00:58 +00:00
|
|
|
for (int i = 1; i < doomcom.numnodes; ++i)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (!gotsetup[i] || netbuffer[0] == NCMD_SETUP+3)
|
|
|
|
{
|
|
|
|
HSendPacket (i, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// D_CheckNetGame
|
|
|
|
// Works out player numbers among the net participants
|
|
|
|
//
|
|
|
|
|
|
|
|
void D_CheckNetGame (void)
|
|
|
|
{
|
|
|
|
const char *v;
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2014-10-05 05:32:32 +00:00
|
|
|
// Packet server has proven to be rather slow over the internet. Print a warning about it.
|
|
|
|
v = Args->CheckValue("-netmode");
|
|
|
|
if (v != NULL && (atoi(v) != 0))
|
|
|
|
{
|
2014-10-05 05:52:56 +00:00
|
|
|
Printf(TEXTCOLOR_YELLOW "Notice: Using PacketServer (netmode 1) over the internet is prone to running too slow on some internet configurations."
|
2014-10-13 23:54:03 +00:00
|
|
|
"\nIf the game is running well below expected speeds, use netmode 0 (P2P) instead.\n");
|
2014-10-05 05:32:32 +00:00
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// I_InitNetwork sets doomcom and netgame
|
2009-01-24 04:47:07 +00:00
|
|
|
if (I_InitNetwork ())
|
|
|
|
{
|
2014-10-05 05:32:32 +00:00
|
|
|
// For now, stop auto selecting PacketServer, as it's more likely to cause confusion.
|
|
|
|
//NetMode = NET_PacketServer;
|
2009-01-24 04:47:07 +00:00
|
|
|
}
|
2006-05-11 04:00:58 +00:00
|
|
|
if (doomcom.id != DOOMCOM_ID)
|
2009-01-24 04:47:07 +00:00
|
|
|
{
|
2006-02-24 04:48:15 +00:00
|
|
|
I_FatalError ("Doomcom buffer invalid!");
|
2009-01-24 04:47:07 +00:00
|
|
|
}
|
2008-02-16 15:02:52 +00:00
|
|
|
players[0].settings_controller = true;
|
2009-01-24 04:47:07 +00:00
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
consoleplayer = doomcom.consoleplayer;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2014-08-21 04:31:29 +00:00
|
|
|
if (consoleplayer == Net_Arbitrator)
|
2009-01-24 04:47:07 +00:00
|
|
|
{
|
2014-08-21 04:31:29 +00:00
|
|
|
v = Args->CheckValue("-netmode");
|
|
|
|
if (v != NULL)
|
|
|
|
{
|
|
|
|
NetMode = atoi(v) != 0 ? NET_PacketServer : NET_PeerToPeer;
|
|
|
|
}
|
|
|
|
if (doomcom.numnodes > 1)
|
|
|
|
{
|
|
|
|
Printf("Selected " TEXTCOLOR_BLUE "%s" TEXTCOLOR_NORMAL " networking mode. (%s)\n", NetMode == NET_PeerToPeer ? "peer to peer" : "packet server",
|
|
|
|
v != NULL ? "forced" : "auto");
|
|
|
|
}
|
2014-08-21 04:41:59 +00:00
|
|
|
|
|
|
|
if (Args->CheckParm("-extratic"))
|
|
|
|
{
|
|
|
|
net_extratic = 1;
|
|
|
|
}
|
2009-01-24 04:47:07 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// [RH] Setup user info
|
|
|
|
D_SetupUserInfo ();
|
|
|
|
|
2008-03-12 02:56:11 +00:00
|
|
|
if (Args->CheckParm ("-debugfile"))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
About a week's worth of changes here. As a heads-up, I wouldn't be
surprised if this doesn't build in Linux right now. The CMakeLists.txt
were checked with MinGW and NMake, but how they fair under Linux is an
unknown to me at this time.
- Converted most sprintf (and all wsprintf) calls to either mysnprintf or
FStrings, depending on the situation.
- Changed the strings in the wbstartstruct to be FStrings.
- Changed myvsnprintf() to output nothing if count is greater than INT_MAX.
This is so that I can use a series of mysnprintf() calls and advance the
pointer for each one. Once the pointer goes beyond the end of the buffer,
the count will go negative, but since it's an unsigned type it will be
seen as excessively huge instead. This should not be a problem, as there's
no reason for ZDoom to be using text buffers larger than 2 GB anywhere.
- Ripped out the disabled bit from FGameConfigFile::MigrateOldConfig().
- Changed CalcMapName() to return an FString instead of a pointer to a static
buffer.
- Changed startmap in d_main.cpp into an FString.
- Changed CheckWarpTransMap() to take an FString& as the first argument.
- Changed d_mapname in g_level.cpp into an FString.
- Changed DoSubstitution() in ct_chat.cpp to place the substitutions in an
FString.
- Fixed: The MAPINFO parser wrote into the string buffer to construct a map
name when given a Hexen map number. This was fine with the old scanner
code, but only a happy coincidence prevents it from crashing with the new
code
- Added the 'B' conversion specifier to StringFormat::VWorker() for printing
binary numbers.
- Added CMake support for building with MinGW, MSYS, and NMake. Linux support
is probably broken until I get around to booting into Linux again. Niceties
provided over the existing Makefiles they're replacing:
* All command-line builds can use the same build system, rather than having
a separate one for MinGW and another for Linux.
* Microsoft's NMake tool is supported as a target.
* Progress meters.
* Parallel makes work from a fresh checkout without needing to be primed
first with a single-threaded make.
* Porting to other architectures should be simplified, whenever that day
comes.
- Replaced the makewad tool with zipdir. This handles the dependency tracking
itself instead of generating an external makefile to do it, since I couldn't
figure out how to generate a makefile with an external tool and include it
with a CMake-generated makefile. Where makewad used a master list of files
to generate the package file, zipdir just zips the entire contents of one or
more directories.
- Added the gdtoa package from netlib's fp library so that ZDoom's printf-style
formatting can be entirely independant of the CRT.
SVN r1082 (trunk)
2008-07-23 04:57:26 +00:00
|
|
|
char filename[20];
|
|
|
|
mysnprintf (filename, countof(filename), "debug%i.txt", consoleplayer);
|
|
|
|
Printf ("debug output to: %s\n", filename);
|
|
|
|
debugfile = fopen (filename, "w");
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (netgame)
|
|
|
|
{
|
|
|
|
GameConfig->ReadNetVars (); // [RH] Read network ServerInfo cvars
|
|
|
|
D_ArbitrateNetStart ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// read values out of doomcom
|
2006-05-11 04:00:58 +00:00
|
|
|
ticdup = doomcom.ticdup;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
for (i = 0; i < doomcom.numplayers; i++)
|
2006-02-24 04:48:15 +00:00
|
|
|
playeringame[i] = true;
|
2006-05-11 04:00:58 +00:00
|
|
|
for (i = 0; i < doomcom.numnodes; i++)
|
2006-02-24 04:48:15 +00:00
|
|
|
nodeingame[i] = true;
|
|
|
|
|
2014-08-21 04:31:29 +00:00
|
|
|
if (consoleplayer != Net_Arbitrator && doomcom.numnodes > 1)
|
|
|
|
{
|
|
|
|
Printf("Arbitrator selected " TEXTCOLOR_BLUE "%s" TEXTCOLOR_NORMAL " networking mode.\n", NetMode == NET_PeerToPeer ? "peer to peer" : "packet server");
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
Printf ("player %i of %i (%i nodes)\n",
|
2006-05-11 04:00:58 +00:00
|
|
|
consoleplayer+1, doomcom.numplayers, doomcom.numnodes);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// D_QuitNetGame
|
|
|
|
// Called before quitting to leave a net game
|
|
|
|
// without hanging the other players
|
|
|
|
//
|
2006-05-12 03:14:40 +00:00
|
|
|
void D_QuitNetGame (void)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
int i, j, k;
|
|
|
|
|
|
|
|
if (!netgame || !usergame || consoleplayer == -1 || demoplayback)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// send a bunch of packets for security
|
|
|
|
netbuffer[0] = NCMD_EXIT;
|
|
|
|
netbuffer[1] = 0;
|
|
|
|
|
|
|
|
k = 2;
|
|
|
|
if (NetMode == NET_PacketServer && consoleplayer == Net_Arbitrator)
|
|
|
|
{
|
|
|
|
BYTE *foo = &netbuffer[2];
|
|
|
|
|
|
|
|
// Let the new arbitrator know what resendto counts to use
|
|
|
|
|
|
|
|
for (i = 0; i < MAXPLAYERS; ++i)
|
|
|
|
{
|
|
|
|
if (playeringame[i] && i != consoleplayer)
|
|
|
|
WriteLong (resendto[nodeforplayer[i]], &foo);
|
|
|
|
}
|
2009-05-15 10:39:40 +00:00
|
|
|
k = int(foo - netbuffer);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
if (NetMode == NET_PacketServer && consoleplayer != Net_Arbitrator)
|
|
|
|
{
|
|
|
|
HSendPacket (nodeforplayer[Net_Arbitrator], 2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-05-11 04:00:58 +00:00
|
|
|
for (j = 1; j < doomcom.numnodes; j++)
|
2006-02-24 04:48:15 +00:00
|
|
|
if (nodeingame[j])
|
|
|
|
HSendPacket (j, k);
|
|
|
|
}
|
|
|
|
I_WaitVBL (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (debugfile)
|
|
|
|
fclose (debugfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// TryRunTics
|
|
|
|
//
|
|
|
|
void TryRunTics (void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int lowtic;
|
|
|
|
int realtics;
|
|
|
|
int availabletics;
|
|
|
|
int counts;
|
|
|
|
int numplaying;
|
|
|
|
|
|
|
|
// If paused, do not eat more CPU time than we need, because it
|
|
|
|
// will all be wasted anyway.
|
2015-02-05 09:43:42 +00:00
|
|
|
if (pauseext) r_NoInterpolate = true;
|
2006-02-24 04:48:15 +00:00
|
|
|
bool doWait = cl_capfps || r_NoInterpolate /*|| netgame*/;
|
|
|
|
|
|
|
|
// get real tics
|
|
|
|
if (doWait)
|
|
|
|
{
|
|
|
|
entertic = I_WaitForTic (oldentertics);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
entertic = I_GetTime (false);
|
|
|
|
}
|
|
|
|
realtics = entertic - oldentertics;
|
|
|
|
oldentertics = entertic;
|
|
|
|
|
|
|
|
// get available tics
|
|
|
|
NetUpdate ();
|
|
|
|
|
|
|
|
lowtic = INT_MAX;
|
|
|
|
numplaying = 0;
|
2006-05-11 04:00:58 +00:00
|
|
|
for (i = 0; i < doomcom.numnodes; i++)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (nodeingame[i])
|
|
|
|
{
|
|
|
|
numplaying++;
|
|
|
|
if (nettics[i] < lowtic)
|
|
|
|
lowtic = nettics[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ticdup == 1)
|
|
|
|
{
|
|
|
|
availabletics = lowtic - gametic;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2014-07-14 10:26:40 +00:00
|
|
|
// Uncapped framerate needs seprate checks
|
2006-02-24 04:48:15 +00:00
|
|
|
if (counts == 0 && !doWait)
|
|
|
|
{
|
2014-01-01 11:04:32 +00:00
|
|
|
// Check possible stall conditions
|
2015-02-09 20:16:57 +00:00
|
|
|
Net_CheckLastReceived(counts);
|
2014-07-14 10:26:40 +00:00
|
|
|
if (realtics >= 1)
|
|
|
|
{
|
|
|
|
C_Ticker();
|
|
|
|
M_Ticker();
|
2014-08-26 10:31:42 +00:00
|
|
|
// Repredict the player for new buffered movement
|
|
|
|
P_UnPredictPlayer();
|
|
|
|
P_PredictPlayer(&players[consoleplayer]);
|
2014-07-14 10:26:40 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (counts < 1)
|
|
|
|
counts = 1;
|
|
|
|
|
|
|
|
if (debugfile)
|
|
|
|
fprintf (debugfile,
|
|
|
|
"=======real: %i avail: %i game: %i\n",
|
|
|
|
realtics, availabletics, counts);
|
|
|
|
|
|
|
|
// wait for new tics if needed
|
|
|
|
while (lowtic < gametic + counts)
|
|
|
|
{
|
|
|
|
NetUpdate ();
|
|
|
|
lowtic = INT_MAX;
|
|
|
|
|
2006-05-11 04:00:58 +00:00
|
|
|
for (i = 0; i < doomcom.numnodes; i++)
|
2006-02-24 04:48:15 +00:00
|
|
|
if (nodeingame[i] && nettics[i] < lowtic)
|
|
|
|
lowtic = nettics[i];
|
|
|
|
|
|
|
|
lowtic = lowtic * ticdup;
|
|
|
|
|
|
|
|
if (lowtic < gametic)
|
|
|
|
I_Error ("TryRunTics: lowtic < gametic");
|
|
|
|
|
2014-01-01 11:04:32 +00:00
|
|
|
// Check possible stall conditions
|
2015-02-09 20:16:57 +00:00
|
|
|
Net_CheckLastReceived (counts);
|
2013-05-25 22:01:26 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// don't stay in here forever -- give the menu a chance to work
|
2014-07-14 10:26:40 +00:00
|
|
|
if (I_GetTime (false) - entertic >= 1)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
C_Ticker ();
|
|
|
|
M_Ticker ();
|
2014-08-26 10:31:42 +00:00
|
|
|
// Repredict the player for new buffered movement
|
|
|
|
P_UnPredictPlayer();
|
|
|
|
P_PredictPlayer(&players[consoleplayer]);
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-11 07:42:54 +00:00
|
|
|
//Tic lowtic is high enough to process this gametic. Clear all possible waiting info
|
|
|
|
hadlate = false;
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
players[i].waiting = false;
|
|
|
|
lastglobalrecvtime = I_GetTime (false); //Update the last time the game tic'd over
|
2013-05-25 22:01:26 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// run the count tics
|
2008-03-13 00:41:16 +00:00
|
|
|
if (counts > 0)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2014-08-26 10:31:42 +00:00
|
|
|
P_UnPredictPlayer();
|
2008-03-13 00:41:16 +00:00
|
|
|
while (counts--)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-03-13 00:41:16 +00:00
|
|
|
if (gametic > lowtic)
|
|
|
|
{
|
|
|
|
I_Error ("gametic>lowtic");
|
|
|
|
}
|
|
|
|
if (advancedemo)
|
|
|
|
{
|
|
|
|
D_DoAdvanceDemo ();
|
|
|
|
}
|
|
|
|
if (debugfile) fprintf (debugfile, "run tic %d\n", gametic);
|
|
|
|
C_Ticker ();
|
|
|
|
M_Ticker ();
|
|
|
|
I_GetTime (true);
|
2015-02-05 09:43:42 +00:00
|
|
|
if (!pauseext) G_Ticker();
|
2008-03-13 00:41:16 +00:00
|
|
|
gametic++;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2008-03-13 00:41:16 +00:00
|
|
|
NetUpdate (); // check for new console commands
|
|
|
|
}
|
2014-08-26 10:31:42 +00:00
|
|
|
P_PredictPlayer(&players[consoleplayer]);
|
2008-03-13 00:41:16 +00:00
|
|
|
S_UpdateSounds (players[consoleplayer].camera); // move positional sounds
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-09 20:16:57 +00:00
|
|
|
void Net_CheckLastReceived (int counts)
|
2014-01-01 11:04:32 +00:00
|
|
|
{
|
2015-02-09 20:16:57 +00:00
|
|
|
// [Ed850] Check to see the last time a packet was received.
|
2014-01-01 11:04:32 +00:00
|
|
|
// If it's longer then 3 seconds, a node has likely stalled.
|
|
|
|
if (I_GetTime(false) - lastglobalrecvtime >= TICRATE * 3)
|
|
|
|
{
|
|
|
|
lastglobalrecvtime = I_GetTime(false); //Bump the count
|
|
|
|
|
|
|
|
if (NetMode == NET_PeerToPeer || consoleplayer == Net_Arbitrator)
|
|
|
|
{
|
|
|
|
//Keep the local node in the for loop so we can still log any cases where the local node is /somehow/ late.
|
|
|
|
//However, we don't send a resend request for sanity reasons.
|
|
|
|
for (int i = 0; i < doomcom.numnodes; i++)
|
|
|
|
{
|
|
|
|
if (nodeingame[i] && nettics[i] <= gametic + counts)
|
|
|
|
{
|
|
|
|
if (debugfile && !players[playerfornode[i]].waiting)
|
|
|
|
fprintf(debugfile, "%i is slow (%i to %i)\n",
|
|
|
|
i, nettics[i], gametic + counts);
|
|
|
|
//Send resend request to the late node. Also mark the node as waiting to display it in the hud.
|
|
|
|
if (i != 0)
|
|
|
|
remoteresend[i] = players[playerfornode[i]].waiting = hadlate = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
players[playerfornode[i]].waiting = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ //Send a resend request to the Arbitrator, as it's obvious we are stuck here.
|
2015-02-09 20:16:57 +00:00
|
|
|
if (debugfile && !players[Net_Arbitrator].waiting)
|
2014-01-01 11:04:32 +00:00
|
|
|
fprintf(debugfile, "Arbitrator is slow (%i to %i)\n",
|
2015-02-09 20:16:57 +00:00
|
|
|
nettics[nodeforplayer[Net_Arbitrator]], gametic + counts);
|
2014-01-01 11:04:32 +00:00
|
|
|
//Send resend request to the Arbitrator. Also mark the Arbitrator as waiting to display it in the hud.
|
2015-02-09 20:16:57 +00:00
|
|
|
remoteresend[nodeforplayer[Net_Arbitrator]] = players[Net_Arbitrator].waiting = hadlate = true;
|
2014-01-01 11:04:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
void Net_NewMakeTic (void)
|
|
|
|
{
|
|
|
|
specials.NewMakeTic ();
|
|
|
|
}
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
void Net_WriteByte (BYTE it)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
specials << it;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Net_WriteWord (short it)
|
|
|
|
{
|
|
|
|
specials << it;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Net_WriteLong (int it)
|
|
|
|
{
|
|
|
|
specials << it;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Net_WriteFloat (float it)
|
|
|
|
{
|
|
|
|
specials << it;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Net_WriteString (const char *it)
|
|
|
|
{
|
|
|
|
specials << it;
|
|
|
|
}
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
void Net_WriteBytes (const BYTE *block, int len)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
while (len--)
|
|
|
|
specials << *block++;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Dynamic buffer interface
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FDynamicBuffer::FDynamicBuffer ()
|
|
|
|
{
|
|
|
|
m_Data = NULL;
|
|
|
|
m_Len = m_BufferLen = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
FDynamicBuffer::~FDynamicBuffer ()
|
|
|
|
{
|
|
|
|
if (m_Data)
|
|
|
|
{
|
|
|
|
free (m_Data);
|
|
|
|
m_Data = NULL;
|
|
|
|
}
|
|
|
|
m_Len = m_BufferLen = 0;
|
|
|
|
}
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
void FDynamicBuffer::SetData (const BYTE *data, int len)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (len > m_BufferLen)
|
|
|
|
{
|
|
|
|
m_BufferLen = (len + 255) & ~255;
|
2006-09-14 00:02:31 +00:00
|
|
|
m_Data = (BYTE *)M_Realloc (m_Data, m_BufferLen);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2015-02-07 16:02:46 +00:00
|
|
|
if (data != NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
m_Len = len;
|
|
|
|
memcpy (m_Data, data, len);
|
|
|
|
}
|
2015-02-08 16:58:24 +00:00
|
|
|
else
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2015-02-07 15:35:23 +00:00
|
|
|
m_Len = 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
BYTE *FDynamicBuffer::GetData (int *len)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (len)
|
|
|
|
*len = m_Len;
|
|
|
|
return m_Len ? m_Data : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-14 03:04:41 +00:00
|
|
|
static int KillAll(PClassActor *cls)
|
2010-08-26 20:59:15 +00:00
|
|
|
{
|
|
|
|
AActor *actor;
|
|
|
|
int killcount = 0;
|
|
|
|
TThinkerIterator<AActor> iterator(cls);
|
|
|
|
while ( (actor = iterator.Next ()) )
|
|
|
|
{
|
|
|
|
if (actor->IsA(cls))
|
|
|
|
{
|
|
|
|
if (!(actor->flags2 & MF2_DORMANT) && (actor->flags3 & MF3_ISMONSTER))
|
|
|
|
killcount += actor->Massacre ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return killcount;
|
|
|
|
|
2015-08-11 01:45:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int RemoveClass(const PClass *cls)
|
|
|
|
{
|
|
|
|
AActor *actor;
|
|
|
|
int removecount = 0;
|
|
|
|
bool player = false;
|
|
|
|
TThinkerIterator<AActor> iterator(cls);
|
|
|
|
while ((actor = iterator.Next()))
|
|
|
|
{
|
|
|
|
if (actor->IsA(cls))
|
|
|
|
{
|
|
|
|
// [MC]Do not remove LIVE players.
|
2015-08-11 11:53:28 +00:00
|
|
|
if (actor->player != NULL)
|
2015-08-11 01:45:18 +00:00
|
|
|
{
|
|
|
|
player = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
removecount++;
|
|
|
|
actor->ClearCounters();
|
|
|
|
actor->Destroy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (player)
|
|
|
|
Printf("Cannot remove live players!\n");
|
|
|
|
return removecount;
|
|
|
|
|
2010-08-26 20:59:15 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
// [RH] Execute a special "ticcmd". The type byte should
|
|
|
|
// have already been read, and the stream is positioned
|
|
|
|
// at the beginning of the command's actual data.
|
2006-09-14 00:02:31 +00:00
|
|
|
void Net_DoCommand (int type, BYTE **stream, int player)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-09-14 00:02:31 +00:00
|
|
|
BYTE pos = 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
char *s = NULL;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case DEM_SAY:
|
|
|
|
{
|
2013-05-12 18:27:03 +00:00
|
|
|
const char *name = players[player].userinfo.GetName();
|
2006-09-14 00:02:31 +00:00
|
|
|
BYTE who = ReadByte (stream);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
s = ReadString (stream);
|
2009-02-20 00:53:25 +00:00
|
|
|
CleanseString (s);
|
2013-05-12 18:27:03 +00:00
|
|
|
if (((who & 1) == 0) || players[player].userinfo.GetTeam() == TEAM_NONE)
|
2006-02-24 04:48:15 +00:00
|
|
|
{ // Said to everyone
|
|
|
|
if (who & 2)
|
|
|
|
{
|
2009-02-20 00:53:25 +00:00
|
|
|
Printf (PRINT_CHAT, TEXTCOLOR_BOLD "* %s" TEXTCOLOR_BOLD "%s" TEXTCOLOR_BOLD "\n", name, s);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-20 00:53:25 +00:00
|
|
|
Printf (PRINT_CHAT, "%s" TEXTCOLOR_CHAT ": %s" TEXTCOLOR_CHAT "\n", name, s);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2008-07-23 19:39:01 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, gameinfo.chatSound, 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2013-05-12 18:27:03 +00:00
|
|
|
else if (players[player].userinfo.GetTeam() == players[consoleplayer].userinfo.GetTeam())
|
2006-02-24 04:48:15 +00:00
|
|
|
{ // Said only to members of the player's team
|
|
|
|
if (who & 2)
|
|
|
|
{
|
2009-02-20 00:53:25 +00:00
|
|
|
Printf (PRINT_TEAMCHAT, TEXTCOLOR_BOLD "* (%s" TEXTCOLOR_BOLD ")%s" TEXTCOLOR_BOLD "\n", name, s);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-20 00:53:25 +00:00
|
|
|
Printf (PRINT_TEAMCHAT, "(%s" TEXTCOLOR_TEAMCHAT "): %s" TEXTCOLOR_TEAMCHAT "\n", name, s);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2008-07-23 19:39:01 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, gameinfo.chatSound, 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_MUSICCHANGE:
|
|
|
|
s = ReadString (stream);
|
|
|
|
S_ChangeMusic (s);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_PRINT:
|
|
|
|
s = ReadString (stream);
|
2009-01-28 05:29:41 +00:00
|
|
|
Printf ("%s", s);
|
2006-02-24 04:48:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_CENTERPRINT:
|
|
|
|
s = ReadString (stream);
|
2008-11-27 17:43:36 +00:00
|
|
|
C_MidPrint (SmallFont, s);
|
2006-02-24 04:48:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_UINFCHANGED:
|
|
|
|
D_ReadUserInfoStrings (player, stream, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_SINFCHANGED:
|
|
|
|
D_DoServerInfoChange (stream, false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_SINFCHANGEDXOR:
|
|
|
|
D_DoServerInfoChange (stream, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_GIVECHEAT:
|
|
|
|
s = ReadString (stream);
|
2006-04-21 05:44:21 +00:00
|
|
|
cht_Give (&players[player], s, ReadWord (stream));
|
2006-02-24 04:48:15 +00:00
|
|
|
break;
|
|
|
|
|
2007-12-23 14:23:52 +00:00
|
|
|
case DEM_TAKECHEAT:
|
|
|
|
s = ReadString (stream);
|
|
|
|
cht_Take (&players[player], s, ReadWord (stream));
|
|
|
|
break;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
case DEM_WARPCHEAT:
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
x = ReadWord (stream);
|
|
|
|
y = ReadWord (stream);
|
|
|
|
P_TeleportMove (players[player].mo, x * 65536, y * 65536, ONFLOORZ, true);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_GENERICCHEAT:
|
|
|
|
cht_DoCheat (&players[player], ReadByte (stream));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_CHANGEMAP2:
|
|
|
|
pos = ReadByte (stream);
|
|
|
|
/* intentional fall-through */
|
|
|
|
case DEM_CHANGEMAP:
|
|
|
|
// Change to another map without disconnecting other players
|
|
|
|
s = ReadString (stream);
|
|
|
|
// Using LEVEL_NOINTERMISSION tends to throw the game out of sync.
|
|
|
|
// That was a long time ago. Maybe it works now?
|
|
|
|
level.flags |= LEVEL_CHANGEMAPCHEAT;
|
2010-06-18 03:35:41 +00:00
|
|
|
G_ChangeLevel(s, pos, 0);
|
2006-02-24 04:48:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_SUICIDE:
|
|
|
|
cht_Suicide (&players[player]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_ADDBOT:
|
2014-10-25 13:58:10 +00:00
|
|
|
bglobal.TryAddBot (stream, player);
|
2006-02-24 04:48:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_KILLBOTS:
|
2008-03-28 00:38:17 +00:00
|
|
|
bglobal.RemoveAllBots (true);
|
2006-02-24 04:48:15 +00:00
|
|
|
Printf ("Removed all bots\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_CENTERVIEW:
|
2012-04-03 04:09:30 +00:00
|
|
|
players[player].centering = true;
|
2006-02-24 04:48:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_INVUSEALL:
|
|
|
|
if (gamestate == GS_LEVEL && !paused)
|
|
|
|
{
|
|
|
|
AInventory *item = players[player].mo->Inventory;
|
|
|
|
|
|
|
|
while (item != NULL)
|
|
|
|
{
|
|
|
|
AInventory *next = item->Inventory;
|
2006-04-11 16:27:41 +00:00
|
|
|
if (item->ItemFlags & IF_INVBAR && !(item->IsKindOf(RUNTIME_CLASS(APuzzleItem))))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
players[player].mo->UseInventory (item);
|
|
|
|
}
|
|
|
|
item = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_INVUSE:
|
|
|
|
case DEM_INVDROP:
|
|
|
|
{
|
|
|
|
DWORD which = ReadLong (stream);
|
|
|
|
|
2014-07-16 00:16:28 +00:00
|
|
|
if (gamestate == GS_LEVEL && !paused
|
|
|
|
&& players[player].playerstate != PST_DEAD)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
AInventory *item = players[player].mo->Inventory;
|
|
|
|
while (item != NULL && item->InventoryID != which)
|
|
|
|
{
|
|
|
|
item = item->Inventory;
|
|
|
|
}
|
|
|
|
if (item != NULL)
|
|
|
|
{
|
|
|
|
if (type == DEM_INVUSE)
|
|
|
|
{
|
|
|
|
players[player].mo->UseInventory (item);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
players[player].mo->DropInventory (item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_SUMMON:
|
|
|
|
case DEM_SUMMONFRIEND:
|
2007-01-16 03:04:00 +00:00
|
|
|
case DEM_SUMMONFOE:
|
2009-09-14 19:44:14 +00:00
|
|
|
case DEM_SUMMONMBF:
|
2008-12-16 01:23:44 +00:00
|
|
|
case DEM_SUMMON2:
|
|
|
|
case DEM_SUMMONFRIEND2:
|
|
|
|
case DEM_SUMMONFOE2:
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-03-25 20:38:00 +00:00
|
|
|
PClassActor *typeinfo;
|
2009-11-08 02:51:22 +00:00
|
|
|
int angle = 0;
|
|
|
|
SWORD tid = 0;
|
|
|
|
BYTE special = 0;
|
2009-08-03 20:40:45 +00:00
|
|
|
int args[5];
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
s = ReadString (stream);
|
2009-08-03 20:40:45 +00:00
|
|
|
if (type >= DEM_SUMMON2 && type <= DEM_SUMMONFOE2)
|
|
|
|
{
|
|
|
|
angle = ReadWord(stream);
|
|
|
|
tid = ReadWord(stream);
|
|
|
|
special = ReadByte(stream);
|
|
|
|
for(i = 0; i < 5; i++) args[i] = ReadLong(stream);
|
|
|
|
}
|
|
|
|
|
2010-03-25 20:38:00 +00:00
|
|
|
typeinfo = PClass::FindActor(s);
|
|
|
|
if (typeinfo != NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
AActor *source = players[player].mo;
|
|
|
|
if (source != NULL)
|
|
|
|
{
|
|
|
|
if (GetDefaultByType (typeinfo)->flags & MF_MISSILE)
|
|
|
|
{
|
|
|
|
P_SpawnPlayerMissile (source, typeinfo);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const AActor *def = GetDefaultByType (typeinfo);
|
|
|
|
AActor *spawned = Spawn (typeinfo,
|
|
|
|
source->x + FixedMul (def->radius * 2 + source->radius, finecosine[source->angle>>ANGLETOFINESHIFT]),
|
|
|
|
source->y + FixedMul (def->radius * 2 + source->radius, finesine[source->angle>>ANGLETOFINESHIFT]),
|
2006-07-16 09:10:45 +00:00
|
|
|
source->z + 8 * FRACUNIT, ALLOW_REPLACE);
|
2007-01-16 03:04:00 +00:00
|
|
|
if (spawned != NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-09-14 19:44:14 +00:00
|
|
|
if (type == DEM_SUMMONFRIEND || type == DEM_SUMMONFRIEND2 || type == DEM_SUMMONMBF)
|
2006-09-20 08:09:00 +00:00
|
|
|
{
|
2007-01-16 03:04:00 +00:00
|
|
|
if (spawned->CountsAsKill())
|
|
|
|
{
|
|
|
|
level.total_monsters--;
|
|
|
|
}
|
|
|
|
spawned->FriendPlayer = player + 1;
|
|
|
|
spawned->flags |= MF_FRIENDLY;
|
|
|
|
spawned->LastHeard = players[player].mo;
|
2009-07-04 18:17:44 +00:00
|
|
|
spawned->health = spawned->SpawnHealth();
|
2009-09-14 19:44:14 +00:00
|
|
|
if (type == DEM_SUMMONMBF)
|
|
|
|
spawned->flags3 |= MF3_NOBLOCKMONST;
|
2007-01-16 03:04:00 +00:00
|
|
|
}
|
2008-12-16 01:23:44 +00:00
|
|
|
else if (type == DEM_SUMMONFOE || type == DEM_SUMMONFOE2)
|
2007-01-16 03:04:00 +00:00
|
|
|
{
|
|
|
|
spawned->FriendPlayer = 0;
|
|
|
|
spawned->flags &= ~MF_FRIENDLY;
|
2009-07-04 18:17:44 +00:00
|
|
|
spawned->health = spawned->SpawnHealth();
|
2006-09-20 08:09:00 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2008-12-16 01:23:44 +00:00
|
|
|
if (type >= DEM_SUMMON2 && type <= DEM_SUMMONFOE2)
|
|
|
|
{
|
|
|
|
spawned->angle = source->angle - (ANGLE_1 * angle);
|
2009-08-03 20:40:45 +00:00
|
|
|
spawned->tid = tid;
|
|
|
|
spawned->special = special;
|
|
|
|
for(i = 0; i < 5; i++) {
|
|
|
|
spawned->args[i] = args[i];
|
|
|
|
}
|
|
|
|
if(tid) spawned->AddToHash();
|
2008-12-16 01:23:44 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-04-21 05:44:21 +00:00
|
|
|
case DEM_SPRAY:
|
|
|
|
{
|
|
|
|
FTraceResults trace;
|
|
|
|
|
|
|
|
angle_t ang = players[player].mo->angle >> ANGLETOFINESHIFT;
|
|
|
|
angle_t pitch = (angle_t)(players[player].mo->pitch) >> ANGLETOFINESHIFT;
|
|
|
|
fixed_t vx = FixedMul (finecosine[pitch], finecosine[ang]);
|
|
|
|
fixed_t vy = FixedMul (finecosine[pitch], finesine[ang]);
|
|
|
|
fixed_t vz = -finesine[pitch];
|
|
|
|
|
|
|
|
s = ReadString (stream);
|
|
|
|
|
|
|
|
if (Trace (players[player].mo->x, players[player].mo->y,
|
|
|
|
players[player].mo->z + players[player].mo->height - (players[player].mo->height>>2),
|
|
|
|
players[player].mo->Sector,
|
|
|
|
vx, vy, vz, 172*FRACUNIT, 0, ML_BLOCKEVERYTHING, players[player].mo,
|
|
|
|
trace, TRACE_NoSky))
|
|
|
|
{
|
|
|
|
if (trace.HitType == TRACE_HitWall)
|
|
|
|
{
|
|
|
|
DImpactDecal::StaticCreate (s,
|
|
|
|
trace.X, trace.Y, trace.Z,
|
2009-09-06 20:45:56 +00:00
|
|
|
trace.Line->sidedef[trace.Side], NULL);
|
2006-04-21 05:44:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
case DEM_PAUSE:
|
|
|
|
if (gamestate == GS_LEVEL)
|
|
|
|
{
|
|
|
|
if (paused)
|
|
|
|
{
|
|
|
|
paused = 0;
|
2009-05-20 02:52:07 +00:00
|
|
|
S_ResumeSound (false);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
paused = player + 1;
|
2009-05-20 02:52:07 +00:00
|
|
|
S_PauseSound (false, false);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2013-02-27 03:10:25 +00:00
|
|
|
V_SetBorderNeedRefresh();
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_SAVEGAME:
|
|
|
|
if (gamestate == GS_LEVEL)
|
|
|
|
{
|
2006-05-12 03:14:40 +00:00
|
|
|
s = ReadString (stream);
|
|
|
|
savegamefile = s;
|
|
|
|
delete[] s;
|
2006-02-24 04:48:15 +00:00
|
|
|
s = ReadString (stream);
|
|
|
|
memset (savedescription, 0, sizeof(savedescription));
|
|
|
|
strncpy (savedescription, s, sizeof(savedescription));
|
|
|
|
if (player != consoleplayer)
|
|
|
|
{
|
|
|
|
// Paths sent over the network will be valid for the system that sent
|
|
|
|
// the save command. For other systems, the path needs to be changed.
|
2006-05-16 02:50:18 +00:00
|
|
|
const char *fileonly = savegamefile.GetChars();
|
2006-05-23 04:25:49 +00:00
|
|
|
const char *slash = strrchr (fileonly, '\\');
|
2006-02-24 04:48:15 +00:00
|
|
|
if (slash != NULL)
|
|
|
|
{
|
|
|
|
fileonly = slash + 1;
|
|
|
|
}
|
|
|
|
slash = strrchr (fileonly, '/');
|
|
|
|
if (slash != NULL)
|
|
|
|
{
|
|
|
|
fileonly = slash + 1;
|
|
|
|
}
|
|
|
|
if (fileonly != savegamefile.GetChars())
|
|
|
|
{
|
|
|
|
savegamefile = G_BuildSaveName (fileonly, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gameaction = ga_savegame;
|
|
|
|
break;
|
|
|
|
|
2006-10-19 20:20:56 +00:00
|
|
|
case DEM_CHECKAUTOSAVE:
|
|
|
|
// Do not autosave in multiplayer games or when dead.
|
|
|
|
// For demo playback, DEM_DOAUTOSAVE already exists in the demo if the
|
|
|
|
// autosave happened. And if it doesn't, we must not generate it.
|
|
|
|
if (multiplayer ||
|
|
|
|
demoplayback ||
|
|
|
|
players[consoleplayer].playerstate != PST_LIVE ||
|
|
|
|
disableautosave >= 2 ||
|
|
|
|
autosavecount == 0)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Net_WriteByte (DEM_DOAUTOSAVE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_DOAUTOSAVE:
|
|
|
|
gameaction = ga_autosave;
|
|
|
|
break;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
case DEM_FOV:
|
|
|
|
{
|
|
|
|
float newfov = (float)ReadByte (stream);
|
|
|
|
|
|
|
|
if (newfov != players[consoleplayer].DesiredFOV)
|
|
|
|
{
|
|
|
|
Printf ("FOV%s set to %g\n",
|
|
|
|
consoleplayer == Net_Arbitrator ? " for everyone" : "",
|
|
|
|
newfov);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < MAXPLAYERS; ++i)
|
|
|
|
{
|
|
|
|
if (playeringame[i])
|
|
|
|
{
|
|
|
|
players[i].DesiredFOV = newfov;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_MYFOV:
|
|
|
|
players[player].DesiredFOV = (float)ReadByte (stream);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_RUNSCRIPT:
|
2006-08-17 00:19:26 +00:00
|
|
|
case DEM_RUNSCRIPT2:
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
int snum = ReadWord (stream);
|
|
|
|
int argn = ReadByte (stream);
|
2012-02-16 22:13:46 +00:00
|
|
|
|
2012-02-26 03:36:05 +00:00
|
|
|
RunScript(stream, players[player].mo, snum, argn, (type == DEM_RUNSCRIPT2) ? ACS_ALWAYS : 0);
|
2012-02-16 22:13:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_RUNNAMEDSCRIPT:
|
|
|
|
{
|
|
|
|
char *sname = ReadString(stream);
|
|
|
|
int argn = ReadByte(stream);
|
|
|
|
|
2012-02-26 03:36:05 +00:00
|
|
|
RunScript(stream, players[player].mo, -FName(sname), argn & 127, (argn & 128) ? ACS_ALWAYS : 0);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2011-01-02 18:54:57 +00:00
|
|
|
case DEM_RUNSPECIAL:
|
|
|
|
{
|
|
|
|
int snum = ReadByte(stream);
|
|
|
|
int argn = ReadByte(stream);
|
|
|
|
int arg[5] = { 0, 0, 0, 0, 0 };
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
for (i = 0; i < argn; ++i)
|
|
|
|
{
|
2011-01-02 18:54:57 +00:00
|
|
|
int argval = ReadLong(stream);
|
2011-02-19 08:59:43 +00:00
|
|
|
if ((unsigned)i < countof(arg))
|
2011-01-02 18:54:57 +00:00
|
|
|
{
|
|
|
|
arg[i] = argval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!CheckCheatmode(player == consoleplayer))
|
|
|
|
{
|
2011-02-13 10:18:28 +00:00
|
|
|
P_ExecuteSpecial(snum, NULL, players[player].mo, false, arg[0], arg[1], arg[2], arg[3], arg[4]);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-05-14 14:30:13 +00:00
|
|
|
case DEM_CROUCH:
|
2006-06-22 09:36:48 +00:00
|
|
|
if (gamestate == GS_LEVEL && players[player].mo != NULL &&
|
2012-01-22 00:31:42 +00:00
|
|
|
players[player].health > 0 && !(players[player].oldbuttons & BT_JUMP) &&
|
|
|
|
!P_IsPlayerTotallyFrozen(&players[player]))
|
2006-05-14 14:30:13 +00:00
|
|
|
{
|
2012-01-22 00:31:42 +00:00
|
|
|
players[player].crouching = players[player].crouchdir < 0 ? 1 : -1;
|
2006-05-14 14:30:13 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-10-27 03:03:34 +00:00
|
|
|
case DEM_MORPHEX:
|
|
|
|
{
|
|
|
|
s = ReadString (stream);
|
2010-03-25 20:38:00 +00:00
|
|
|
const char *msg = cht_Morph (players + player, dyn_cast<PClassPlayerPawn>(PClass::FindClass (s)), false);
|
2006-10-27 03:03:34 +00:00
|
|
|
if (player == consoleplayer)
|
|
|
|
{
|
|
|
|
Printf ("%s\n", *msg != '\0' ? msg : "Morph failed.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2006-05-14 14:30:13 +00:00
|
|
|
|
2008-02-16 15:02:52 +00:00
|
|
|
case DEM_ADDCONTROLLER:
|
|
|
|
{
|
|
|
|
BYTE playernum = ReadByte (stream);
|
|
|
|
players[playernum].settings_controller = true;
|
|
|
|
|
|
|
|
if (consoleplayer == playernum || consoleplayer == Net_Arbitrator)
|
2013-05-12 18:27:03 +00:00
|
|
|
Printf ("%s has been added to the controller list.\n", players[playernum].userinfo.GetName());
|
2008-02-16 15:02:52 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_DELCONTROLLER:
|
|
|
|
{
|
|
|
|
BYTE playernum = ReadByte (stream);
|
|
|
|
players[playernum].settings_controller = false;
|
|
|
|
|
|
|
|
if (consoleplayer == playernum || consoleplayer == Net_Arbitrator)
|
2013-05-12 18:27:03 +00:00
|
|
|
Printf ("%s has been removed from the controller list.\n", players[playernum].userinfo.GetName());
|
2008-02-16 15:02:52 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-02-20 21:28:55 +00:00
|
|
|
case DEM_KILLCLASSCHEAT:
|
|
|
|
{
|
|
|
|
char *classname = ReadString (stream);
|
|
|
|
int killcount = 0;
|
2010-09-16 03:14:32 +00:00
|
|
|
PClassActor *cls = PClass::FindActor(classname);
|
2008-02-20 21:28:55 +00:00
|
|
|
|
2010-09-16 03:14:32 +00:00
|
|
|
if (cls != NULL)
|
2008-02-20 21:28:55 +00:00
|
|
|
{
|
2010-08-26 20:59:15 +00:00
|
|
|
killcount = KillAll(cls);
|
2012-07-14 03:04:41 +00:00
|
|
|
PClassActor *cls_rep = cls->GetReplacement();
|
2010-08-26 20:59:15 +00:00
|
|
|
if (cls != cls_rep)
|
2008-02-20 21:28:55 +00:00
|
|
|
{
|
2010-08-26 20:59:15 +00:00
|
|
|
killcount += KillAll(cls_rep);
|
2008-02-20 21:28:55 +00:00
|
|
|
}
|
2010-09-05 20:51:13 +00:00
|
|
|
Printf ("Killed %d monsters of type %s.\n",killcount, classname);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Printf ("%s is not an actor class.\n", classname);
|
2008-02-20 21:28:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
2015-08-11 01:45:18 +00:00
|
|
|
case DEM_REMOVE:
|
|
|
|
{
|
|
|
|
char *classname = ReadString(stream);
|
|
|
|
int removecount = 0;
|
2016-01-17 18:09:05 +00:00
|
|
|
PClassActor *cls = PClass::FindActor(classname);
|
|
|
|
if (cls != NULL && cls->IsKindOf(RUNTIME_CLASS(PClassActor)))
|
2015-08-11 01:45:18 +00:00
|
|
|
{
|
|
|
|
removecount = RemoveClass(cls);
|
|
|
|
const PClass *cls_rep = cls->GetReplacement();
|
|
|
|
if (cls != cls_rep)
|
|
|
|
{
|
|
|
|
removecount += RemoveClass(cls_rep);
|
|
|
|
}
|
|
|
|
Printf("Removed %d actors of type %s.\n", removecount, classname);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Printf("%s is not an actor class.\n", classname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2008-02-20 21:28:55 +00:00
|
|
|
|
2010-01-22 05:17:57 +00:00
|
|
|
case DEM_CONVREPLY:
|
|
|
|
case DEM_CONVCLOSE:
|
|
|
|
case DEM_CONVNULL:
|
|
|
|
P_ConversationCommand (type, player, stream);
|
2008-03-26 08:29:02 +00:00
|
|
|
break;
|
|
|
|
|
2009-02-20 22:28:48 +00:00
|
|
|
case DEM_SETSLOT:
|
2012-03-22 22:29:25 +00:00
|
|
|
case DEM_SETSLOTPNUM:
|
2009-02-20 22:28:48 +00:00
|
|
|
{
|
2012-03-22 22:29:25 +00:00
|
|
|
int pnum;
|
|
|
|
if (type == DEM_SETSLOTPNUM)
|
|
|
|
{
|
|
|
|
pnum = ReadByte(stream);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pnum = player;
|
|
|
|
}
|
2009-02-24 05:58:59 +00:00
|
|
|
unsigned int slot = ReadByte(stream);
|
|
|
|
int count = ReadByte(stream);
|
|
|
|
if (slot < NUM_WEAPON_SLOTS)
|
|
|
|
{
|
2012-03-22 22:29:25 +00:00
|
|
|
players[pnum].weapons.Slots[slot].Clear();
|
2009-02-24 05:58:59 +00:00
|
|
|
}
|
2011-02-19 08:59:43 +00:00
|
|
|
for(i = 0; i < count; ++i)
|
2009-02-20 22:28:48 +00:00
|
|
|
{
|
2010-03-25 20:38:00 +00:00
|
|
|
PClassWeapon *wpn = Net_ReadWeapon(stream);
|
2012-03-22 22:29:25 +00:00
|
|
|
players[pnum].weapons.AddSlot(slot, wpn, pnum == consoleplayer);
|
2009-02-20 22:28:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_ADDSLOT:
|
|
|
|
{
|
2009-02-24 05:58:59 +00:00
|
|
|
int slot = ReadByte(stream);
|
2010-03-25 20:38:00 +00:00
|
|
|
PClassWeapon *wpn = Net_ReadWeapon(stream);
|
2009-02-24 05:58:59 +00:00
|
|
|
players[player].weapons.AddSlot(slot, wpn, player == consoleplayer);
|
2009-02-20 22:28:48 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_ADDSLOTDEFAULT:
|
|
|
|
{
|
2009-02-24 05:58:59 +00:00
|
|
|
int slot = ReadByte(stream);
|
2010-03-25 20:38:00 +00:00
|
|
|
PClassWeapon *wpn = Net_ReadWeapon(stream);
|
2009-02-24 05:58:59 +00:00
|
|
|
players[player].weapons.AddSlotDefault(slot, wpn, player == consoleplayer);
|
2009-02-20 22:28:48 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2011-12-06 01:25:37 +00:00
|
|
|
case DEM_SETPITCHLIMIT:
|
|
|
|
players[player].MinPitch = ReadByte(stream) * -ANGLE_1; // up
|
|
|
|
players[player].MaxPitch = ReadByte(stream) * ANGLE_1; // down
|
|
|
|
break;
|
|
|
|
|
2011-12-06 02:51:32 +00:00
|
|
|
case DEM_ADVANCEINTER:
|
|
|
|
F_AdvanceIntermission();
|
|
|
|
break;
|
|
|
|
|
2012-03-17 00:52:33 +00:00
|
|
|
case DEM_REVERTCAMERA:
|
|
|
|
players[player].camera = players[player].mo;
|
|
|
|
break;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
default:
|
|
|
|
I_Error ("Unknown net command: %d", type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s)
|
|
|
|
delete[] s;
|
|
|
|
}
|
|
|
|
|
2012-02-16 22:13:46 +00:00
|
|
|
// Used by DEM_RUNSCRIPT, DEM_RUNSCRIPT2, and DEM_RUNNAMEDSCRIPT
|
2012-02-26 03:36:05 +00:00
|
|
|
static void RunScript(BYTE **stream, APlayerPawn *pawn, int snum, int argn, int always)
|
2012-02-16 22:13:46 +00:00
|
|
|
{
|
2012-02-26 03:36:05 +00:00
|
|
|
int arg[4] = { 0, 0, 0, 0 };
|
2012-02-16 22:13:46 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < argn; ++i)
|
|
|
|
{
|
|
|
|
int argval = ReadLong(stream);
|
|
|
|
if ((unsigned)i < countof(arg))
|
|
|
|
{
|
|
|
|
arg[i] = argval;
|
|
|
|
}
|
|
|
|
}
|
2014-05-13 21:16:13 +00:00
|
|
|
P_StartScript(pawn, NULL, snum, level.MapName, arg, MIN<int>(countof(arg), argn), ACS_NET | always);
|
2012-02-16 22:13:46 +00:00
|
|
|
}
|
|
|
|
|
2006-09-14 00:02:31 +00:00
|
|
|
void Net_SkipCommand (int type, BYTE **stream)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
BYTE t;
|
|
|
|
size_t skip;
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case DEM_SAY:
|
|
|
|
skip = strlen ((char *)(*stream + 1)) + 2;
|
|
|
|
break;
|
|
|
|
|
2014-10-14 18:57:11 +00:00
|
|
|
case DEM_ADDBOT:
|
|
|
|
skip = strlen ((char *)(*stream + 1)) + 6;
|
|
|
|
break;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
case DEM_GIVECHEAT:
|
2007-12-23 14:23:52 +00:00
|
|
|
case DEM_TAKECHEAT:
|
2009-08-03 20:40:45 +00:00
|
|
|
skip = strlen ((char *)(*stream)) + 3;
|
|
|
|
break;
|
|
|
|
|
2008-12-16 01:23:44 +00:00
|
|
|
case DEM_SUMMON2:
|
|
|
|
case DEM_SUMMONFRIEND2:
|
|
|
|
case DEM_SUMMONFOE2:
|
2009-08-03 20:40:45 +00:00
|
|
|
skip = strlen ((char *)(*stream)) + 26;
|
2006-02-24 04:48:15 +00:00
|
|
|
break;
|
2015-01-24 03:09:15 +00:00
|
|
|
case DEM_CHANGEMAP2:
|
|
|
|
skip = strlen((char *)(*stream + 1)) + 2;
|
|
|
|
break;
|
2006-02-24 04:48:15 +00:00
|
|
|
case DEM_MUSICCHANGE:
|
|
|
|
case DEM_PRINT:
|
|
|
|
case DEM_CENTERPRINT:
|
|
|
|
case DEM_UINFCHANGED:
|
|
|
|
case DEM_CHANGEMAP:
|
|
|
|
case DEM_SUMMON:
|
2006-04-21 05:44:21 +00:00
|
|
|
case DEM_SUMMONFRIEND:
|
2007-01-16 03:04:00 +00:00
|
|
|
case DEM_SUMMONFOE:
|
2009-09-14 19:44:14 +00:00
|
|
|
case DEM_SUMMONMBF:
|
2015-08-11 11:53:28 +00:00
|
|
|
case DEM_REMOVE:
|
2006-04-21 05:44:21 +00:00
|
|
|
case DEM_SPRAY:
|
2006-10-27 03:03:34 +00:00
|
|
|
case DEM_MORPHEX:
|
2008-02-20 21:28:55 +00:00
|
|
|
case DEM_KILLCLASSCHEAT:
|
2006-02-24 04:48:15 +00:00
|
|
|
skip = strlen ((char *)(*stream)) + 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_INVUSE:
|
|
|
|
case DEM_INVDROP:
|
|
|
|
case DEM_WARPCHEAT:
|
|
|
|
skip = 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_GENERICCHEAT:
|
|
|
|
case DEM_DROPPLAYER:
|
|
|
|
case DEM_FOV:
|
|
|
|
case DEM_MYFOV:
|
2008-02-16 15:02:52 +00:00
|
|
|
case DEM_ADDCONTROLLER:
|
|
|
|
case DEM_DELCONTROLLER:
|
2006-02-24 04:48:15 +00:00
|
|
|
skip = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_SAVEGAME:
|
|
|
|
skip = strlen ((char *)(*stream)) + 1;
|
|
|
|
skip += strlen ((char *)(*stream) + skip) + 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_SINFCHANGEDXOR:
|
|
|
|
case DEM_SINFCHANGED:
|
|
|
|
t = **stream;
|
|
|
|
skip = 1 + (t & 63);
|
|
|
|
if (type == DEM_SINFCHANGED)
|
|
|
|
{
|
|
|
|
switch (t >> 6)
|
|
|
|
{
|
|
|
|
case CVAR_Bool:
|
|
|
|
skip += 1;
|
|
|
|
break;
|
|
|
|
case CVAR_Int: case CVAR_Float:
|
|
|
|
skip += 4;
|
|
|
|
break;
|
|
|
|
case CVAR_String:
|
|
|
|
skip += strlen ((char *)(*stream + skip)) + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
skip += 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_RUNSCRIPT:
|
2006-08-17 00:19:26 +00:00
|
|
|
case DEM_RUNSCRIPT2:
|
2006-02-24 04:48:15 +00:00
|
|
|
skip = 3 + *(*stream + 2) * 4;
|
|
|
|
break;
|
|
|
|
|
2012-02-16 22:13:46 +00:00
|
|
|
case DEM_RUNNAMEDSCRIPT:
|
|
|
|
skip = strlen((char *)(*stream)) + 2;
|
|
|
|
skip += ((*(*stream + skip - 1)) & 127) * 4;
|
|
|
|
break;
|
|
|
|
|
2011-01-02 18:54:57 +00:00
|
|
|
case DEM_RUNSPECIAL:
|
|
|
|
skip = 2 + *(*stream + 1) * 4;
|
|
|
|
break;
|
|
|
|
|
2010-01-22 05:17:57 +00:00
|
|
|
case DEM_CONVREPLY:
|
|
|
|
skip = 3;
|
2008-03-26 08:29:02 +00:00
|
|
|
break;
|
|
|
|
|
2009-02-20 22:28:48 +00:00
|
|
|
case DEM_SETSLOT:
|
2012-03-22 22:29:25 +00:00
|
|
|
case DEM_SETSLOTPNUM:
|
2009-02-20 22:28:48 +00:00
|
|
|
{
|
2012-03-22 22:29:25 +00:00
|
|
|
skip = 2 + (type == DEM_SETSLOTPNUM);
|
|
|
|
for(int numweapons = (*stream)[skip-1]; numweapons > 0; numweapons--)
|
2009-02-20 22:28:48 +00:00
|
|
|
{
|
2009-02-24 05:58:59 +00:00
|
|
|
skip += 1 + ((*stream)[skip] >> 7);
|
2009-02-20 22:28:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEM_ADDSLOT:
|
|
|
|
case DEM_ADDSLOTDEFAULT:
|
2009-02-24 05:58:59 +00:00
|
|
|
skip = 2 + ((*stream)[1] >> 7);
|
2009-02-20 22:28:48 +00:00
|
|
|
break;
|
|
|
|
|
2011-12-06 01:25:37 +00:00
|
|
|
case DEM_SETPITCHLIMIT:
|
|
|
|
skip = 2;
|
|
|
|
break;
|
2009-02-20 22:28:48 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
*stream += skip;
|
|
|
|
}
|
|
|
|
|
|
|
|
// [RH] List "ping" times
|
|
|
|
CCMD (pings)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
|
|
if (playeringame[i])
|
|
|
|
Printf ("% 4d %s\n", currrecvtime[i] - lastrecvtime[i],
|
2013-05-12 18:27:03 +00:00
|
|
|
players[i].userinfo.GetName());
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2008-02-16 15:02:52 +00:00
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Network_Controller
|
|
|
|
//
|
|
|
|
// Implement players who have the ability to change settings in a network
|
|
|
|
// game.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void Network_Controller (int playernum, bool add)
|
|
|
|
{
|
|
|
|
if (consoleplayer != Net_Arbitrator)
|
|
|
|
{
|
|
|
|
Printf ("This command is only accessible to the net arbitrator.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (players[playernum].settings_controller && add)
|
|
|
|
{
|
2013-05-12 18:27:03 +00:00
|
|
|
Printf ("%s is already on the setting controller list.\n", players[playernum].userinfo.GetName());
|
2008-02-16 15:02:52 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!players[playernum].settings_controller && !add)
|
|
|
|
{
|
2013-05-12 18:27:03 +00:00
|
|
|
Printf ("%s is not on the setting controller list.\n", players[playernum].userinfo.GetName());
|
2008-02-16 15:02:52 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!playeringame[playernum])
|
|
|
|
{
|
2008-02-22 00:20:11 +00:00
|
|
|
Printf ("Player (%d) not found!\n", playernum);
|
2008-02-16 15:02:52 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-14 18:57:11 +00:00
|
|
|
if (players[playernum].Bot != NULL)
|
2008-02-16 15:02:52 +00:00
|
|
|
{
|
|
|
|
Printf ("Bots cannot be added to the controller list.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (playernum == Net_Arbitrator)
|
|
|
|
{
|
|
|
|
Printf ("The net arbitrator cannot have their status changed on this list.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (add)
|
|
|
|
Net_WriteByte (DEM_ADDCONTROLLER);
|
|
|
|
else
|
|
|
|
Net_WriteByte (DEM_DELCONTROLLER);
|
|
|
|
|
|
|
|
Net_WriteByte (playernum);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CCMD net_addcontroller
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CCMD (net_addcontroller)
|
|
|
|
{
|
|
|
|
if (!netgame)
|
|
|
|
{
|
|
|
|
Printf ("This command can only be used when playing a net game.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv.argc () < 2)
|
|
|
|
{
|
|
|
|
Printf ("Usage: net_addcontroller <player>\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Network_Controller (atoi (argv[1]), true);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CCMD net_removecontroller
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CCMD (net_removecontroller)
|
|
|
|
{
|
|
|
|
if (!netgame)
|
|
|
|
{
|
|
|
|
Printf ("This command can only be used when playing a net game.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv.argc () < 2)
|
|
|
|
{
|
|
|
|
Printf ("Usage: net_removecontroller <player>\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Network_Controller (atoi (argv[1]), false);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CCMD net_listcontrollers
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CCMD (net_listcontrollers)
|
|
|
|
{
|
|
|
|
if (!netgame)
|
|
|
|
{
|
|
|
|
Printf ("This command can only be used when playing a net game.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Printf ("The following players can change the game settings:\n");
|
|
|
|
|
|
|
|
for (int i = 0; i < MAXPLAYERS; i++)
|
|
|
|
{
|
|
|
|
if (!playeringame[i])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (players[i].settings_controller)
|
|
|
|
{
|
2013-05-12 18:27:03 +00:00
|
|
|
Printf ("- %s\n", players[i].userinfo.GetName());
|
2008-02-16 15:02:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|