Merge branch 'clientserver' into HEAD

This commit is contained in:
Rachael Alexanderson 2018-06-04 02:31:11 -04:00
commit 8881ef52dc
64 changed files with 2015 additions and 3367 deletions

View file

@ -876,6 +876,9 @@ set (PCH_SOURCES
d_main.cpp
d_stats.cpp
d_net.cpp
d_netsingle.cpp
d_netserver.cpp
d_netclient.cpp
d_netinfo.cpp
d_protocol.cpp
decallib.cpp

View file

@ -48,6 +48,8 @@
#include "tflags.h"
#include "portal.h"
#include "d_netsync.h"
struct subsector_t;
struct FBlockNode;
struct FPortalGroupArray;
@ -635,6 +637,9 @@ public:
AActor &operator= (const AActor &other);
~AActor ();
NetSyncData syncdata;
NetSyncData synccompare;
virtual void Finalize(FStateDefinitions &statedef);
virtual void OnDestroy() override;
virtual void Serialize(FSerializer &arc) override;

View file

@ -212,7 +212,7 @@ CCMD (removebots)
return;
}
Net_WriteByte (DEM_KILLBOTS);
network->WriteByte (DEM_KILLBOTS);
}
CCMD (freeze)
@ -226,8 +226,8 @@ CCMD (freeze)
return;
}
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_FREEZE);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_FREEZE);
}
CCMD (listbots)

View file

@ -314,8 +314,8 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
thebot->inuse = BOTINUSE_Waiting;
Net_WriteByte (DEM_ADDBOT);
Net_WriteByte (botshift);
network->WriteByte (DEM_ADDBOT);
network->WriteByte (botshift);
{
//Set color.
char concat[512];
@ -329,12 +329,12 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
mysnprintf (concat + strlen(concat), countof(concat) - strlen(concat),
"\\team\\%d\n", thebot->lastteam);
}
Net_WriteString (concat);
network->WriteString (concat);
}
Net_WriteByte(thebot->skill.aiming);
Net_WriteByte(thebot->skill.perfection);
Net_WriteByte(thebot->skill.reaction);
Net_WriteByte(thebot->skill.isp);
network->WriteByte(thebot->skill.aiming);
network->WriteByte(thebot->skill.perfection);
network->WriteByte(thebot->skill.reaction);
network->WriteByte(thebot->skill.isp);
return true;
}

View file

@ -58,9 +58,7 @@ static FRandom pr_botmove ("BotMove");
//so this is what the bot does.
void DBot::Think ()
{
ticcmd_t *cmd = &netcmds[player - players][((gametic + 1)/ticdup)%BACKUPTICS];
memset (cmd, 0, sizeof(*cmd));
ticcmd_t cmd;
if (enemy && enemy->health <= 0)
enemy = NULL;
@ -75,16 +73,16 @@ void DBot::Think ()
DAngle oldpitch = actor->Angles.Pitch;
Set_enemy ();
ThinkForMove (cmd);
ThinkForMove (&cmd);
TurnToAng ();
cmd->ucmd.yaw = (short)((actor->Angles.Yaw - oldyaw).Degrees * (65536 / 360.f)) / ticdup;
cmd->ucmd.pitch = (short)((oldpitch - actor->Angles.Pitch).Degrees * (65536 / 360.f));
if (cmd->ucmd.pitch == -32768)
cmd->ucmd.pitch = -32767;
cmd->ucmd.pitch /= ticdup;
actor->Angles.Yaw = oldyaw + DAngle(cmd->ucmd.yaw * ticdup * (360 / 65536.f));
actor->Angles.Pitch = oldpitch - DAngle(cmd->ucmd.pitch * ticdup * (360 / 65536.f));
cmd.ucmd.yaw = (short)((actor->Angles.Yaw - oldyaw).Degrees * (65536 / 360.f)) / network->ticdup;
cmd.ucmd.pitch = (short)((oldpitch - actor->Angles.Pitch).Degrees * (65536 / 360.f));
if (cmd.ucmd.pitch == -32768)
cmd.ucmd.pitch = -32767;
cmd.ucmd.pitch /= network->ticdup;
actor->Angles.Yaw = oldyaw + DAngle(cmd.ucmd.yaw * network->ticdup * (360 / 65536.f));
actor->Angles.Pitch = oldpitch - DAngle(cmd.ucmd.pitch * network->ticdup * (360 / 65536.f));
}
if (t_active) t_active--;
@ -101,8 +99,10 @@ void DBot::Think ()
}
else if (player->mo->health <= 0)
{ // Time to respawn
cmd->ucmd.buttons |= BT_USE;
cmd.ucmd.buttons |= BT_USE;
}
network->WriteBotInput((int)(player - players), cmd);
}
#define THINKDISTSQ (50000.*50000./(65536.*65536.))

View file

@ -117,8 +117,8 @@ CCMD (god)
if (CheckCheatmode ())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_GOD);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_GOD);
}
CCMD(god2)
@ -126,8 +126,8 @@ CCMD(god2)
if (CheckCheatmode())
return;
Net_WriteByte(DEM_GENERICCHEAT);
Net_WriteByte(CHT_GOD2);
network->WriteByte(DEM_GENERICCHEAT);
network->WriteByte(CHT_GOD2);
}
CCMD (iddqd)
@ -135,8 +135,8 @@ CCMD (iddqd)
if (CheckCheatmode ())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_IDDQD);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_IDDQD);
}
CCMD (buddha)
@ -144,8 +144,8 @@ CCMD (buddha)
if (CheckCheatmode())
return;
Net_WriteByte(DEM_GENERICCHEAT);
Net_WriteByte(CHT_BUDDHA);
network->WriteByte(DEM_GENERICCHEAT);
network->WriteByte(CHT_BUDDHA);
}
CCMD(buddha2)
@ -153,8 +153,8 @@ CCMD(buddha2)
if (CheckCheatmode())
return;
Net_WriteByte(DEM_GENERICCHEAT);
Net_WriteByte(CHT_BUDDHA2);
network->WriteByte(DEM_GENERICCHEAT);
network->WriteByte(CHT_BUDDHA2);
}
CCMD (notarget)
@ -162,8 +162,8 @@ CCMD (notarget)
if (CheckCheatmode ())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_NOTARGET);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_NOTARGET);
}
CCMD (fly)
@ -171,8 +171,8 @@ CCMD (fly)
if (CheckCheatmode ())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_FLY);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_FLY);
}
/*
@ -187,8 +187,8 @@ CCMD (noclip)
if (CheckCheatmode ())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_NOCLIP);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_NOCLIP);
}
CCMD (noclip2)
@ -196,8 +196,8 @@ CCMD (noclip2)
if (CheckCheatmode())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_NOCLIP2);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_NOCLIP2);
}
CCMD (powerup)
@ -205,8 +205,8 @@ CCMD (powerup)
if (CheckCheatmode ())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_POWER);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_POWER);
}
CCMD (morphme)
@ -216,13 +216,13 @@ CCMD (morphme)
if (argv.argc() == 1)
{
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_MORPH);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_MORPH);
}
else
{
Net_WriteByte (DEM_MORPHEX);
Net_WriteString (argv[1]);
network->WriteByte (DEM_MORPHEX);
network->WriteString (argv[1]);
}
}
@ -231,8 +231,8 @@ CCMD (anubis)
if (CheckCheatmode ())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_ANUBIS);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_ANUBIS);
}
// [GRB]
@ -241,8 +241,8 @@ CCMD (resurrect)
if (CheckCheatmode ())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_RESSURECT);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_RESSURECT);
}
EXTERN_CVAR (Bool, chasedemo)
@ -273,8 +273,8 @@ CCMD (chase)
if (gamestate != GS_LEVEL || (!(dmflags2 & DF2_CHASECAM) && deathmatch && CheckCheatmode ()))
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_CHASECAM);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_CHASECAM);
}
}
@ -372,14 +372,14 @@ CCMD (changemap)
{
if (argv.argc() > 2)
{
Net_WriteByte (DEM_CHANGEMAP2);
Net_WriteByte (atoi(argv[2]));
network->WriteByte (DEM_CHANGEMAP2);
network->WriteByte (atoi(argv[2]));
}
else
{
Net_WriteByte (DEM_CHANGEMAP);
network->WriteByte (DEM_CHANGEMAP);
}
Net_WriteString (mapname);
network->WriteString (mapname);
}
}
catch(CRecoverableError &error)
@ -399,12 +399,12 @@ CCMD (give)
if (CheckCheatmode () || argv.argc() < 2)
return;
Net_WriteByte (DEM_GIVECHEAT);
Net_WriteString (argv[1]);
network->WriteByte (DEM_GIVECHEAT);
network->WriteString (argv[1]);
if (argv.argc() > 2)
Net_WriteLong(atoi(argv[2]));
network->WriteLong(atoi(argv[2]));
else
Net_WriteLong(0);
network->WriteLong(0);
}
CCMD (take)
@ -412,12 +412,12 @@ CCMD (take)
if (CheckCheatmode () || argv.argc() < 2)
return;
Net_WriteByte (DEM_TAKECHEAT);
Net_WriteString (argv[1]);
network->WriteByte (DEM_TAKECHEAT);
network->WriteString (argv[1]);
if (argv.argc() > 2)
Net_WriteLong(atoi (argv[2]));
network->WriteLong(atoi (argv[2]));
else
Net_WriteLong (0);
network->WriteLong (0);
}
CCMD(setinv)
@ -425,17 +425,17 @@ CCMD(setinv)
if (CheckCheatmode() || argv.argc() < 2)
return;
Net_WriteByte(DEM_SETINV);
Net_WriteString(argv[1]);
network->WriteByte(DEM_SETINV);
network->WriteString(argv[1]);
if (argv.argc() > 2)
Net_WriteLong(atoi(argv[2]));
network->WriteLong(atoi(argv[2]));
else
Net_WriteLong(0);
network->WriteLong(0);
if (argv.argc() > 3)
Net_WriteByte(!!atoi(argv[3]));
network->WriteByte(!!atoi(argv[3]));
else
Net_WriteByte(0);
network->WriteByte(0);
}
@ -533,18 +533,18 @@ CCMD (puke)
if (script > 0)
{
Net_WriteByte (DEM_RUNSCRIPT);
Net_WriteWord (script);
network->WriteByte (DEM_RUNSCRIPT);
network->WriteWord (script);
}
else
{
Net_WriteByte (DEM_RUNSCRIPT2);
Net_WriteWord (-script);
network->WriteByte (DEM_RUNSCRIPT2);
network->WriteWord (-script);
}
Net_WriteByte (argn);
network->WriteByte (argn);
for (i = 0; i < argn; ++i)
{
Net_WriteLong (arg[i]);
network->WriteLong (arg[i]);
}
}
}
@ -577,12 +577,12 @@ CCMD (pukename)
arg[i] = atoi(argv[argstart + i]);
}
}
Net_WriteByte(DEM_RUNNAMEDSCRIPT);
Net_WriteString(argv[1]);
Net_WriteByte(argn | (always << 7));
network->WriteByte(DEM_RUNNAMEDSCRIPT);
network->WriteString(argv[1]);
network->WriteByte(argn | (always << 7));
for (i = 0; i < argn; ++i)
{
Net_WriteLong(arg[i]);
network->WriteLong(arg[i]);
}
}
}
@ -623,12 +623,12 @@ CCMD (special)
return;
}
}
Net_WriteByte(DEM_RUNSPECIAL);
Net_WriteWord(specnum);
Net_WriteByte(argc - 2);
network->WriteByte(DEM_RUNSPECIAL);
network->WriteWord(specnum);
network->WriteByte(argc - 2);
for (int i = 2; i < argc; ++i)
{
Net_WriteLong(atoi(argv[i]));
network->WriteLong(atoi(argv[i]));
}
}
}
@ -774,10 +774,10 @@ CCMD (warp)
}
else
{
Net_WriteByte (DEM_WARPCHEAT);
Net_WriteWord (atoi (argv[1]));
Net_WriteWord (atoi (argv[2]));
Net_WriteWord (argv.argc() == 3 ? ONFLOORZ/65536 : atoi (argv[3]));
network->WriteByte (DEM_WARPCHEAT);
network->WriteWord (atoi (argv[1]));
network->WriteWord (atoi (argv[2]));
network->WriteWord (argv.argc() == 3 ? ONFLOORZ/65536 : atoi (argv[3]));
}
}
@ -1078,8 +1078,8 @@ CCMD(thaw)
if (CheckCheatmode())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_CLEARFROZENPROPS);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_CLEARFROZENPROPS);
}
//-----------------------------------------------------------------------------

View file

@ -1238,7 +1238,7 @@ void C_FullConsole ()
{
if (demoplayback)
G_CheckDemoStatus ();
D_QuitNetGame ();
network->D_QuitNetGame ();
advancedemo = false;
ConsoleState = c_down;
HistPos = NULL;

View file

@ -1159,7 +1159,7 @@ void FBaseCVar::MarkUnsafe()
// This type of cvar is not a "real" cvar. Instead, it gets and sets
// the value of a FIntCVar, modifying it bit-by-bit. As such, it has
// no default, and is not written to the .cfg or transferred around
// the network. The "host" cvar is responsible for that.
// the network-> The "host" cvar is responsible for that.
//
FFlagCVar::FFlagCVar (const char *name, FIntCVar &realvar, uint32_t bitval)

View file

@ -621,7 +621,7 @@ void C_DoCommand (const char *cmd, int keynum)
button->ReleaseKey (keynum);
if (button == &Button_Mlook && lookspring)
{
Net_WriteByte (DEM_CENTERVIEW);
network->WriteByte (DEM_CENTERVIEW);
}
}
return;

View file

@ -349,16 +349,16 @@ static void ShoveChatStr (const char *str, uint8_t who)
who |= 2;
}
Net_WriteByte (DEM_SAY);
Net_WriteByte (who);
network->WriteByte (DEM_SAY);
network->WriteByte (who);
if (!chat_substitution || !DoSubstitution (substBuff, str))
{
Net_WriteString (str);
network->WriteString (str);
}
else
{
Net_WriteString (substBuff);
network->WriteString (substBuff);
}
}

View file

@ -119,17 +119,13 @@ typedef enum
// Called by IO functions when input is detected.
void D_PostEvent (const event_t* ev);
void D_RemoveNextCharEvent();
void D_AddPostedEvents();
//
// GLOBAL VARIABLES
//
#define MAXEVENTS 128
extern event_t events[MAXEVENTS];
extern int eventhead;
extern int eventtail;
extern gameaction_t gameaction;

View file

@ -97,6 +97,7 @@
#include "vm.h"
#include "types.h"
#include "r_data/r_vanillatrans.h"
#include "d_netsingle.h"
EXTERN_CVAR(Bool, hud_althud)
void DrawHUD();
@ -122,9 +123,7 @@ const FIWADInfo *D_FindIWAD(TArray<FString> &wadfiles, const char *iwad, const c
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
void D_CheckNetGame ();
void D_ProcessEvents ();
void G_BuildTiccmd (ticcmd_t* cmd);
void D_DoAdvanceDemo ();
void D_AddWildFile (TArray<FString> &wadfiles, const char *pattern);
void D_LoadWadSettings ();
@ -218,9 +217,10 @@ FString StoredWarp;
bool advancedemo;
FILE *debugfile;
FILE *hashfile;
event_t events[MAXEVENTS];
int eventhead;
int eventtail;
static TArray<event_t> FrameStartInputEvents;
static event_t events[MAXEVENTS];
static int eventhead;
static int eventtail;
gamestate_t wipegamestate = GS_DEMOSCREEN; // can be -1 to force a wipe
bool PageBlank;
FTexture *Page;
@ -301,33 +301,46 @@ void D_ProcessEvents (void)
void D_PostEvent (const event_t *ev)
{
// Do not post duplicate consecutive EV_DeviceChange events.
if (ev->type == EV_DeviceChange && events[eventhead].type == EV_DeviceChange)
FrameStartInputEvents.Push(*ev);
}
void D_AddPostedEvents()
{
unsigned int c = FrameStartInputEvents.Size();
for (unsigned int i = 0; i < c; i++)
{
return;
const event_t *ev = &FrameStartInputEvents[i];
// Do not post duplicate consecutive EV_DeviceChange events.
if (ev->type == EV_DeviceChange && events[eventhead].type == EV_DeviceChange)
{
continue;
}
events[eventhead] = *ev;
if (ev->type == EV_Mouse && menuactive == MENU_Off && ConsoleState != c_down && ConsoleState != c_falling && !E_Responder(ev) && !paused)
{
if (Button_Mlook.bDown || freelook)
{
int look = int(ev->y * m_pitch * mouse_sensitivity * 16.0);
if (invertmouse)
look = -look;
G_AddViewPitch(look, true);
events[eventhead].y = 0;
}
if (!Button_Strafe.bDown && !lookstrafe)
{
G_AddViewAngle(int(ev->x * m_yaw * mouse_sensitivity * 8.0), true);
events[eventhead].x = 0;
}
if ((events[eventhead].x | events[eventhead].y) == 0)
{
continue;
}
}
eventhead = (eventhead + 1)&(MAXEVENTS - 1);
}
events[eventhead] = *ev;
if (ev->type == EV_Mouse && menuactive == MENU_Off && ConsoleState != c_down && ConsoleState != c_falling && !E_Responder(ev) && !paused)
{
if (Button_Mlook.bDown || freelook)
{
int look = int(ev->y * m_pitch * mouse_sensitivity * 16.0);
if (invertmouse)
look = -look;
G_AddViewPitch (look, true);
events[eventhead].y = 0;
}
if (!Button_Strafe.bDown && !lookstrafe)
{
G_AddViewAngle (int(ev->x * m_yaw * mouse_sensitivity * 8.0), true);
events[eventhead].x = 0;
}
if ((events[eventhead].x | events[eventhead].y) == 0)
{
return;
}
}
eventhead = (eventhead+1)&(MAXEVENTS-1);
FrameStartInputEvents.Clear();
}
//==========================================================================
@ -380,14 +393,14 @@ CUSTOM_CVAR (Int, dmflags, 0, CVAR_SERVERINFO)
if (self & DF_NO_FREELOOK)
{
Net_WriteByte (DEM_CENTERVIEW);
network->WriteByte (DEM_CENTERVIEW);
}
// If nofov is set, force everybody to the arbitrator's FOV.
if ((self & DF_NO_FOV) && consoleplayer == Net_Arbitrator)
{
float fov;
Net_WriteByte (DEM_FOV);
network->WriteByte (DEM_FOV);
// If the game is started with DF_NO_FOV set, the arbitrator's
// DesiredFOV will not be set when this callback is run, so
@ -397,7 +410,7 @@ CUSTOM_CVAR (Int, dmflags, 0, CVAR_SERVERINFO)
{
fov = 90;
}
Net_WriteFloat (fov);
network->WriteFloat (fov);
}
}
@ -899,7 +912,6 @@ void D_Display ()
if (!wipe || NoWipe < 0)
{
NetUpdate (); // send out any new accumulation
// normal update
// draw ZScript UI stuff
C_DrawConsole (); // draw console
@ -918,7 +930,6 @@ void D_Display ()
screen->WipeEndScreen ();
wipestart = I_msTime();
NetUpdate(); // send out any new accumulation
do
{
@ -933,7 +944,6 @@ void D_Display ()
C_DrawConsole (); // console and
M_Drawer (); // menu are drawn even on top of wipes
screen->Update (); // page flip or blit buffer
NetUpdate (); // [RH] not sure this is needed anymore
} while (!done);
screen->WipeCleanup();
I_FreezeTime(false);
@ -955,10 +965,10 @@ void D_ErrorCleanup ()
{
savegamerestore = false;
bglobal.RemoveAllBots (true);
D_QuitNetGame ();
network->D_QuitNetGame ();
if (demorecording || demoplayback)
G_CheckDemoStatus ();
Net_ClearBuffers ();
network->Net_ClearBuffers ();
G_NewInit ();
M_ClearMenus ();
singletics = false;
@ -982,53 +992,132 @@ void D_ErrorCleanup ()
//
//==========================================================================
void D_DoomLoop ()
class GameTime
{
int lasttic = 0;
public:
void Update()
{
LastTic = CurrentTic;
I_SetFrameTime();
CurrentTic = I_GetTime();
}
int TicsElapsed() const
{
return CurrentTic - LastTic;
}
int BaseGameTic() const
{
return LastTic;
}
int BaseMakeTic() const
{
return LastTic + 1;
}
private:
int LastTic = 0;
int CurrentTic = 0;
} gametime;
class GameInput
{
public:
void Update()
{
// Not sure why the joystick can't be updated every frame..
bool updateJoystick = gametime.TicsElapsed() > 0;
if (updateJoystick)
{
I_StartFrame(); // To do: rename this silly function to I_UpdateJoystick
}
// Grab input events at the beginning of the frame.
// This ensures the mouse movement matches I_GetTimeFrac precisely.
I_StartTic(); // To do: rename this to I_ProcessWindowMessages
}
void BeforeDisplayUpdate()
{
// Apply the events we recorded in I_StartTic as the events for the next frame.
D_AddPostedEvents();
}
} input;
ticcmd_t G_BuildTiccmd();
class PlaySim
{
public:
void Update()
{
int tics = gametime.TicsElapsed();
if (tics == 0)
return;
P_UnPredictPlayer();
D_ProcessEvents();
for (int i = 0; i < tics; i++)
{
network->SetCurrentTic(gametime.BaseGameTic() + i, gametime.BaseMakeTic() + i);
network->WriteLocalInput(G_BuildTiccmd());
if (advancedemo)
D_DoAdvanceDemo();
C_Ticker();
M_Ticker();
G_Ticker();
network->EndCurrentTic();
}
P_PredictPlayer(&players[consoleplayer]);
S_UpdateSounds(players[consoleplayer].camera); // move positional sounds
}
} playsim;
class GameDisplay
{
public:
void Update()
{
// Render frame and present
D_Display();
}
} display;
void D_DoomLoop()
{
// Clamp the timer to TICRATE until the playloop has been entered.
r_NoInterpolate = true;
Page = Advisory = NULL;
vid_cursor.Callback();
for (;;)
while (true)
{
try
{
// frame syncronous IO operations
if (gametic > lasttic)
{
lasttic = gametic;
I_StartFrame ();
}
I_SetFrameTime();
gametime.Update();
if (netconnect)
netconnect->Update();
network->Update();
input.Update();
playsim.Update();
input.BeforeDisplayUpdate();
display.Update();
GC::CheckGC();
// process one or more tics
if (singletics)
{
I_StartTic ();
D_ProcessEvents ();
G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
if (advancedemo)
D_DoAdvanceDemo ();
C_Ticker ();
M_Ticker ();
G_Ticker ();
// [RH] Use the consoleplayer's camera to update sounds
S_UpdateSounds (players[consoleplayer].camera); // move positional sounds
gametic++;
maketic++;
GC::CheckGC ();
Net_NewMakeTic ();
}
else
{
TryRunTics (); // will run at least one tic
}
// Update display, next frame, with current state.
I_StartTic ();
D_Display ();
if (wantToRestart)
{
wantToRestart = false;
@ -1037,11 +1126,11 @@ void D_DoomLoop ()
}
catch (CRecoverableError &error)
{
if (error.GetMessage ())
if (error.GetMessage())
{
Printf (PRINT_BOLD, "\n%s\n", error.GetMessage());
Printf(PRINT_BOLD, "\n%s\n", error.GetMessage());
}
D_ErrorCleanup ();
D_ErrorCleanup();
}
catch (CVMAbortException &error)
{
@ -2313,6 +2402,8 @@ void D_DoomMain (void)
D_DoomInit();
network.reset(new NetSinglePlayer());
extern void D_ConfirmSendStats();
D_ConfirmSendStats();
@ -2593,9 +2684,7 @@ void D_DoomMain (void)
if (!restart)
{
if (!batchrun) Printf ("D_CheckNetGame: Checking network game status.\n");
StartScreen->LoadingStatus ("Checking network game status.", 0x3f);
D_CheckNetGame ();
D_SetupUserInfo();
}
// [SP] Force vanilla transparency auto-detection to re-detect our game lumps now
@ -2610,7 +2699,7 @@ void D_DoomMain (void)
// [RH] Run any saved commands from the command line or autoexec.cfg now.
gamestate = GS_FULLCONSOLE;
Net_NewMakeTic ();
network->Startup();
DThinker::RunThinkers ();
gamestate = GS_STARTUP;
@ -2693,7 +2782,7 @@ void D_DoomMain (void)
G_BeginRecording(NULL);
}
atterm(D_QuitNetGame); // killough
atterm([] { network->D_QuitNetGame(); }); // killough
}
}
}
@ -2867,7 +2956,7 @@ void FStartupScreen::NetInit(char const *,int) {}
void FStartupScreen::NetProgress(int) {}
void FStartupScreen::NetMessage(char const *,...) {}
void FStartupScreen::NetDone(void) {}
bool FStartupScreen::NetLoop(bool (*)(void *),void *) { return false; }
bool FStartupScreen::NetLoop(std::function<bool()> callback) { return false; }
DEFINE_FIELD_X(InputEventData, event_t, type)
DEFINE_FIELD_X(InputEventData, event_t, subtype)

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,7 @@
// Copyright 1993-1996 id Software
// Copyright 1999-2016 Randy Heit
// Copyright 2002-2016 Christoph Oelckers
// Copyright 2018 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -17,141 +18,109 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//-----------------------------------------------------------------------------
//
// DESCRIPTION:
// Networking stuff.
//
//-----------------------------------------------------------------------------
#ifndef __D_NET__
#define __D_NET__
#pragma once
#include "doomtype.h"
#include "doomdef.h"
#include "d_protocol.h"
#include "i_net.h"
#include <memory>
//
// Network play related stuff.
// There is a data struct that stores network
// communication related stuff, and another
// one that defines the actual packets to
// be transmitted.
//
#define DOOMCOM_ID 0x12345678l
#define MAXNETNODES 8 // max computers in a game
#define BACKUPTICS 36 // number of tics to remember
#define MAXTICDUP 5
#define LOCALCMDTICS (BACKUPTICS*MAXTICDUP)
#ifdef DJGPP
// The DOS drivers provide a pretty skimpy buffer.
// Probably not enough.
#define MAX_MSGLEN (BACKUPTICS*10)
#else
#define MAX_MSGLEN 14000
#endif
#define CMD_SEND 1
#define CMD_GET 2
//
// Network packet data.
//
struct doomcom_t
{
uint32_t id; // should be DOOMCOM_ID
int16_t intnum; // DOOM executes an int to execute commands
// communication between DOOM and the driver
int16_t command; // CMD_SEND or CMD_GET
int16_t remotenode; // dest for send, set by get (-1 = no packet).
int16_t datalength; // bytes in doomdata to be sent
// info common to all nodes
int16_t numnodes; // console is always node 0.
int16_t ticdup; // 1 = no duplication, 2-5 = dup for slow nets
#ifdef DJGPP
int16_t pad[5]; // keep things aligned for DOS drivers
#endif
// info specific to this node
int16_t consoleplayer;
int16_t numplayers;
#ifdef DJGPP
int16_t angleoffset; // does not work, but needed to preserve
int16_t drone; // alignment for DOS drivers
#endif
// packet data to be sent
uint8_t data[MAX_MSGLEN];
};
class FDynamicBuffer
{
public:
FDynamicBuffer ();
~FDynamicBuffer ();
FDynamicBuffer();
FDynamicBuffer(const FDynamicBuffer &src);
~FDynamicBuffer();
void SetData (const uint8_t *data, int len);
uint8_t *GetData (int *len = NULL);
FDynamicBuffer &operator=(const FDynamicBuffer &src);
void Clear() { SetData(nullptr, 0); }
void SetData(const uint8_t *data, int len);
void AppendData(const uint8_t *data, int len);
uint8_t *GetData() { return m_Len ? m_Data : nullptr; }
const uint8_t *GetData() const { return m_Len ? m_Data : nullptr; }
int GetSize() const { return m_Len; }
private:
uint8_t *m_Data;
int m_Len, m_BufferLen;
uint8_t *m_Data = nullptr;
int m_Len = 0;
int m_BufferLen = 0;
};
extern FDynamicBuffer NetSpecs[MAXPLAYERS][BACKUPTICS];
class Network
{
public:
virtual ~Network() { }
// Create any new ticcmds and broadcast to other players.
void NetUpdate (void);
// Check for incoming packets
virtual void Update() = 0;
// Broadcasts special packets to other players
// to notify of game exit
void D_QuitNetGame (void);
// Set current tic for reading and writing
virtual void SetCurrentTic(int receivetic, int sendtic) = 0;
//? how many ticks to run?
void TryRunTics (void);
// Send any pending outgoing data
virtual void EndCurrentTic() = 0;
//Use for checking to see if the netgame has stalled
void Net_CheckLastReceived(int);
// Retrieve data about the current tic
virtual int GetSendTick() const = 0;
virtual ticcmd_t GetPlayerInput(int player) const = 0;
virtual ticcmd_t GetSentInput(int tic) const = 0;
// [RH] Functions for making and using special "ticcmds"
void Net_NewMakeTic ();
void Net_WriteByte (uint8_t);
void Net_WriteWord (short);
void Net_WriteLong (int);
void Net_WriteFloat (float);
void Net_WriteString (const char *);
void Net_WriteBytes (const uint8_t *, int len);
// Run network commands for the current tic
virtual void RunCommands(int player) = 0;
// Write outgoing data for the current tic
virtual void WriteLocalInput(ticcmd_t cmd) = 0;
virtual void WriteBotInput(int player, const ticcmd_t &cmd) = 0;
virtual void WriteBytes(const uint8_t *block, int len) = 0;
void WriteByte(uint8_t it);
void WriteWord(short it);
void WriteLong(int it);
void WriteFloat(float it);
void WriteString(const char *it);
// Statistics
virtual int GetPing(int player) const = 0;
virtual int GetServerPing() const = 0;
int GetHighPingThreshold() const;
// CCMDs
virtual void ListPingTimes() = 0;
virtual void Network_Controller(int playernum, bool add) = 0;
// Old init/deinit stuff
void Startup() { }
void Net_ClearBuffers() { }
void D_QuitNetGame() { }
// Demo recording
size_t CopySpecData(int player, uint8_t *dest, size_t dest_size) { return 0; }
// Obsolete; only needed for p2p
bool IsInconsistent(int player, int16_t checkvalue) const { return false; }
void SetConsistency(int player, int16_t checkvalue) { }
int16_t GetConsoleConsistency() const { return 0; }
// Should probably be removed.
int ticdup = 1;
};
extern std::unique_ptr<Network> network;
extern std::unique_ptr<Network> netconnect;
void Net_DoCommand (int type, uint8_t **stream, int player);
void Net_SkipCommand (int type, uint8_t **stream);
void Net_RunCommands (FDynamicBuffer &buffer, int player);
void Net_ClearBuffers ();
// Netgame stuff (buffers and pointers, i.e. indices).
// This is the interface to the packet driver, a separate program
// in DOS, but just an abstraction here.
extern doomcom_t doomcom;
extern struct ticcmd_t localcmds[LOCALCMDTICS];
extern int maketic;
extern int nettics[MAXNETNODES];
extern int netdelay[MAXNETNODES][BACKUPTICS];
extern int nodeforplayer[MAXPLAYERS];
extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
extern int ticdup;
// Old packet format. Kept for reference. Should be removed or updated once the c/s migration is complete.
// [RH]
// New generic packet structure:
@ -167,7 +136,7 @@ extern int ticdup;
// - The first player's consolenum is not included in this list, because it always matches the sender
//
// For each tic:
// Two bytes with consistancy check, followed by tic data
// Two bytes with consistency check, followed by tic data
//
// Setup packets are different, and are described just before D_ArbitrateNetStart().
@ -183,4 +152,14 @@ extern int ticdup;
#define NCMD_1TICS 0x01 // packet contains 1 tic
#define NCMD_0TICS 0x00 // packet contains 0 tics
#endif
enum
{
PRE_CONNECT, // Sent from guest to host for initial connection
PRE_KEEPALIVE,
PRE_DISCONNECT, // Sent from guest that aborts the game
PRE_ALLHERE, // Sent from host to guest when everybody has connected
PRE_CONACK, // Sent from host to guest to acknowledge PRE_CONNECT receipt
PRE_ALLFULL, // Sent from host to an unwanted guest
PRE_ALLHEREACK, // Sent from guest to host to acknowledge PRE_ALLHEREACK receipt
PRE_GO // Sent from host to guest to continue game startup
};

283
src/d_netclient.cpp Normal file
View file

@ -0,0 +1,283 @@
//-----------------------------------------------------------------------------
//
// Copyright 1993-1996 id Software
// Copyright 1999-2016 Randy Heit
// Copyright 2002-2016 Christoph Oelckers
// Copyright 2018 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
#include <stddef.h>
#include <inttypes.h>
#include "version.h"
#include "menu/menu.h"
#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"
#include "d_netclient.h"
#include "d_netsingle.h"
#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"
#include "p_trace.h"
#include "a_sharedglobal.h"
#include "st_start.h"
#include "teaminfo.h"
#include "p_conversation.h"
#include "g_level.h"
#include "d_event.h"
#include "m_argv.h"
#include "p_lnspec.h"
#include "v_video.h"
#include "p_spec.h"
#include "hardware.h"
#include "r_utility.h"
#include "a_keys.h"
#include "intermission/intermission.h"
#include "g_levellocals.h"
#include "events.h"
#include "i_time.h"
NetClient::NetClient(FString server)
{
Printf("Connecting to %s..\n", server.GetChars());
mComm = I_InitNetwork(0);
mServerNode = mComm->Connect(server);
mStatus = NodeStatus::InPreGame;
NetPacket packet;
packet.node = mServerNode;
packet.size = 1;
packet[0] = (uint8_t)NetPacketType::ConnectRequest;
mComm->PacketSend(packet);
}
void NetClient::Update()
{
while (true)
{
NetPacket packet;
mComm->PacketGet(packet);
if (packet.node == -1)
break;
if (packet.node != mServerNode)
{
mComm->Close(packet.node);
}
else if (packet.size == 0)
{
OnClose(packet);
break;
}
else
{
NetPacketType type = (NetPacketType)packet[0];
switch (type)
{
default: OnClose(packet); break;
case NetPacketType::ConnectResponse: OnConnectResponse(packet); break;
case NetPacketType::Disconnect: OnDisconnect(packet); break;
case NetPacketType::Tic: OnTic(packet); break;
}
}
if (mStatus == NodeStatus::Closed)
{
if (network.get() == this)
{
network.reset(new NetSinglePlayer());
G_EndNetGame();
}
else
{
netconnect.reset();
}
return;
}
}
}
void NetClient::SetCurrentTic(int receivetic, int sendtic)
{
gametic = receivetic;
mSendTic = sendtic;
}
void NetClient::EndCurrentTic()
{
NetPacket packet;
packet.node = mServerNode;
packet.size = 2 + sizeof(usercmd_t);
packet[0] = (uint8_t)NetPacketType::Tic;
packet[1] = 0; // target gametic
memcpy(&packet[2], &mCurrentInput[consoleplayer].ucmd, sizeof(usercmd_t));
mComm->PacketSend(packet);
mCurrentCommands = mSendCommands;
mSendCommands.Clear();
}
int NetClient::GetSendTick() const
{
return mSendTic;
}
ticcmd_t NetClient::GetPlayerInput(int player) const
{
return mCurrentInput[player];
}
ticcmd_t NetClient::GetSentInput(int tic) const
{
return mSentInput[tic % BACKUPTICS];
}
void NetClient::RunCommands(int player)
{
if (player == consoleplayer)
{
Net_RunCommands(mCurrentCommands, consoleplayer);
}
}
void NetClient::WriteLocalInput(ticcmd_t cmd)
{
mCurrentInput[consoleplayer] = cmd;
mSentInput[gametic % BACKUPTICS] = cmd;
}
void NetClient::WriteBotInput(int player, const ticcmd_t &cmd)
{
mCurrentInput[player] = cmd;
}
void NetClient::WriteBytes(const uint8_t *block, int len)
{
mSendCommands.AppendData(block, len);
}
int NetClient::GetPing(int player) const
{
return 0;
}
int NetClient::GetServerPing() const
{
return 0;
}
void NetClient::ListPingTimes()
{
}
void NetClient::Network_Controller(int playernum, bool add)
{
}
void NetClient::OnClose(const NetPacket &packet)
{
mComm->Close(mServerNode);
mServerNode = -1;
mStatus = NodeStatus::Closed;
if (network.get() == this)
{
Printf("Disconnected\n");
}
else
{
Printf("Could not connect\n");
}
}
void NetClient::OnConnectResponse(const NetPacket &packet)
{
if (packet.size != 3)
return;
int version = packet[1]; // Protocol version
if (version == 1)
{
if (packet[2] != 255) // Join accepted
{
mPlayer = packet[2];
mStatus = NodeStatus::InGame;
G_InitClientNetGame(mPlayer, "e1m1");
network = std::move(netconnect);
}
else // Server full
{
mComm->Close(mServerNode);
mServerNode = -1;
mStatus = NodeStatus::Closed;
Printf("Could not connect: server is full!\n");
}
}
else
{
Printf("Could not connect: version mismatch.\n");
mComm->Close(mServerNode);
mServerNode = -1;
mStatus = NodeStatus::Closed;
}
}
void NetClient::OnDisconnect(const NetPacket &packet)
{
mComm->Close(packet.node);
mServerNode = -1;
mStatus = NodeStatus::Closed;
}
void NetClient::OnTic(const NetPacket &packet)
{
if (packet.size != 2 + sizeof(float) * 5)
return;
int tic = packet[1];
float x = *(float*)&packet[2];
float y = *(float*)&packet[6];
float z = *(float*)&packet[10];
float yaw = *(float*)&packet[14];
float pitch = *(float*)&packet[18];
if (playeringame[consoleplayer] && players[consoleplayer].mo)
{
players[consoleplayer].mo->SetXYZ(x, y, z);
players[consoleplayer].mo->Angles.Yaw = yaw;
players[consoleplayer].mo->Angles.Pitch = pitch;
}
}

68
src/d_netclient.h Normal file
View file

@ -0,0 +1,68 @@
//-----------------------------------------------------------------------------
//
// Copyright 1993-1996 id Software
// Copyright 1999-2016 Randy Heit
// Copyright 2002-2016 Christoph Oelckers
// Copyright 2018 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
#pragma once
#include "d_netserver.h"
class NetClient : public Network
{
public:
NetClient(FString server);
void Update() override;
void SetCurrentTic(int receivetic, int sendtic) override;
void EndCurrentTic() override;
int GetSendTick() const override;
ticcmd_t GetPlayerInput(int player) const override;
ticcmd_t GetSentInput(int tic) const override;
void RunCommands(int player) override;
void WriteLocalInput(ticcmd_t cmd) override;
void WriteBotInput(int player, const ticcmd_t &cmd) override;
void WriteBytes(const uint8_t *block, int len) override;
int GetPing(int player) const override;
int GetServerPing() const override;
void ListPingTimes() override;
void Network_Controller(int playernum, bool add) override;
private:
void OnClose(const NetPacket &packet);
void OnConnectResponse(const NetPacket &packet);
void OnDisconnect(const NetPacket &packet);
void OnTic(const NetPacket &packet);
std::unique_ptr<doomcom_t> mComm;
int mServerNode = -1;
int mPlayer = -1;
NodeStatus mStatus = NodeStatus::Closed;
int mSendTic = 0;
ticcmd_t mCurrentInput[MAXPLAYERS];
ticcmd_t mSentInput[BACKUPTICS];
FDynamicBuffer mCurrentCommands;
FDynamicBuffer mSendCommands;
};

View file

@ -540,8 +540,8 @@ void D_UserInfoChanged (FBaseCVar *cvar)
mysnprintf (foo, countof(foo), "\\%s\\%s", cvar->GetName(), escaped_val.GetChars());
Net_WriteByte (DEM_UINFCHANGED);
Net_WriteString (foo);
network->WriteByte (DEM_UINFCHANGED);
network->WriteString (foo);
}
static const char *SetServerVar (char *name, ECVarType type, uint8_t **stream, bool singlebit)
@ -624,15 +624,15 @@ void D_SendServerInfoChange (const FBaseCVar *cvar, UCVarValue value, ECVarType
namelen = strlen (cvar->GetName ());
Net_WriteByte (DEM_SINFCHANGED);
Net_WriteByte ((uint8_t)(namelen | (type << 6)));
Net_WriteBytes ((uint8_t *)cvar->GetName (), (int)namelen);
network->WriteByte (DEM_SINFCHANGED);
network->WriteByte ((uint8_t)(namelen | (type << 6)));
network->WriteBytes ((uint8_t *)cvar->GetName (), (int)namelen);
switch (type)
{
case CVAR_Bool: Net_WriteByte (value.Bool); break;
case CVAR_Int: Net_WriteLong (value.Int); break;
case CVAR_Float: Net_WriteFloat (value.Float); break;
case CVAR_String: Net_WriteString (value.String); break;
case CVAR_Bool: network->WriteByte (value.Bool); break;
case CVAR_Int: network->WriteLong (value.Int); break;
case CVAR_Float: network->WriteFloat (value.Float); break;
case CVAR_String: network->WriteString (value.String); break;
default: break; // Silence GCC
}
}
@ -643,10 +643,10 @@ void D_SendServerFlagChange (const FBaseCVar *cvar, int bitnum, bool set)
namelen = (int)strlen (cvar->GetName ());
Net_WriteByte (DEM_SINFCHANGEDXOR);
Net_WriteByte ((uint8_t)namelen);
Net_WriteBytes ((uint8_t *)cvar->GetName (), namelen);
Net_WriteByte (uint8_t(bitnum | (set << 5)));
network->WriteByte (DEM_SINFCHANGEDXOR);
network->WriteByte ((uint8_t)namelen);
network->WriteBytes ((uint8_t *)cvar->GetName (), namelen);
network->WriteByte (uint8_t(bitnum | (set << 5)));
}
void D_DoServerInfoChange (uint8_t **stream, bool singlebit)

305
src/d_netserver.cpp Normal file
View file

@ -0,0 +1,305 @@
//-----------------------------------------------------------------------------
//
// Copyright 1993-1996 id Software
// Copyright 1999-2016 Randy Heit
// Copyright 2002-2016 Christoph Oelckers
// Copyright 2018 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
#include <stddef.h>
#include <inttypes.h>
#include "version.h"
#include "menu/menu.h"
#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"
#include "d_netserver.h"
#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"
#include "p_trace.h"
#include "a_sharedglobal.h"
#include "st_start.h"
#include "teaminfo.h"
#include "p_conversation.h"
#include "g_level.h"
#include "d_event.h"
#include "m_argv.h"
#include "p_lnspec.h"
#include "v_video.h"
#include "p_spec.h"
#include "hardware.h"
#include "r_utility.h"
#include "a_keys.h"
#include "intermission/intermission.h"
#include "g_levellocals.h"
#include "events.h"
#include "i_time.h"
NetServer::NetServer()
{
Printf("Started hosting multiplayer game..\n");
mComm = I_InitNetwork(DOOMPORT);
G_InitServerNetGame("e1m1");
}
void NetServer::Update()
{
while (true)
{
NetPacket packet;
mComm->PacketGet(packet);
if (packet.node == -1)
break;
NetNode &node = mNodes[packet.node];
if (packet.size == 0)
{
OnClose(node, packet);
}
else
{
NetPacketType type = (NetPacketType)packet[0];
switch (type)
{
default: OnClose(node, packet); break;
case NetPacketType::ConnectRequest: OnConnectRequest(node, packet); break;
case NetPacketType::Disconnect: OnDisconnect(node, packet); break;
case NetPacketType::Tic: OnTic(node, packet); break;
}
}
}
}
void NetServer::SetCurrentTic(int receivetic, int sendtic)
{
gametic = receivetic;
mSendTic = sendtic;
}
void NetServer::EndCurrentTic()
{
for (int i = 0; i < MAXNETNODES; i++)
{
if (mNodes[i].Status == NodeStatus::InGame)
{
NetPacket packet;
packet.node = i;
packet.size = 2 + sizeof(float) * 5;
packet[0] = (uint8_t)NetPacketType::Tic;
packet[1] = gametic;
int player = mNodes[i].Player;
if (playeringame[player] && players[player].mo)
{
*(float*)&packet[2] = (float)players[player].mo->X();
*(float*)&packet[6] = (float)players[player].mo->Y();
*(float*)&packet[10] = (float)players[player].mo->Z();
*(float*)&packet[14] = (float)players[player].mo->Angles.Yaw.Degrees;
*(float*)&packet[18] = (float)players[player].mo->Angles.Pitch.Degrees;
}
else
{
*(float*)&packet[2] = 0.0f;
*(float*)&packet[6] = 0.0f;
*(float*)&packet[10] = 0.0f;
*(float*)&packet[14] = 0.0f;
*(float*)&packet[18] = 0.0f;
}
mComm->PacketSend(packet);
}
}
mCurrentCommands = mSendCommands;
mSendCommands.Clear();
}
int NetServer::GetSendTick() const
{
return mSendTic;
}
ticcmd_t NetServer::GetPlayerInput(int player) const
{
return mCurrentInput[player];
}
ticcmd_t NetServer::GetSentInput(int tic) const
{
return mCurrentInput[consoleplayer];
}
void NetServer::RunCommands(int player)
{
if (player == consoleplayer)
{
Net_RunCommands(mCurrentCommands, consoleplayer);
}
}
void NetServer::WriteLocalInput(ticcmd_t cmd)
{
mCurrentInput[consoleplayer] = cmd;
}
void NetServer::WriteBotInput(int player, const ticcmd_t &cmd)
{
mCurrentInput[player] = cmd;
}
void NetServer::WriteBytes(const uint8_t *block, int len)
{
mSendCommands.AppendData(block, len);
}
int NetServer::GetPing(int player) const
{
return 0;
}
int NetServer::GetServerPing() const
{
return 0;
}
void NetServer::ListPingTimes()
{
#if 0
for (int i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
Printf("% 4" PRId64 " %s\n", currrecvtime[i] - lastrecvtime[i], players[i].userinfo.GetName());
#endif
}
void NetServer::Network_Controller(int playernum, bool add)
{
}
void NetServer::OnClose(NetNode &node, const NetPacket &packet)
{
if (node.Status == NodeStatus::InGame)
{
Printf("Player %d left the server", node.Player);
playeringame[node.Player] = false;
players[node.Player].settings_controller = false;
node.Player = -1;
}
node.Status = NodeStatus::Closed;
mComm->Close(packet.node);
}
void NetServer::OnConnectRequest(NetNode &node, const NetPacket &packet)
{
// Search for a spot in the player list
if (node.Status != NodeStatus::InGame)
{
for (int i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
{
node.Player = i;
playeringame[i] = true;
players[i].settings_controller = false;
break;
}
}
}
if (node.Player != -1) // Join accepted.
{
Printf("Player %d joined the server", node.Player);
mNodeForPlayer[node.Player] = packet.node;
NetPacket response;
response.node = packet.node;
response[0] = (uint8_t)NetPacketType::ConnectResponse;
response[1] = 1; // Protocol version
response[2] = node.Player;
response.size = 3;
mComm->PacketSend(response);
node.Status = NodeStatus::InGame;
}
else // Server is full.
{
node.Status = NodeStatus::Closed;
NetPacket response;
response.node = packet.node;
response[0] = (uint8_t)NetPacketType::ConnectResponse;
response[1] = 1; // Protocol version
response[2] = 255;
response.size = 3;
mComm->PacketSend(response);
node.Status = NodeStatus::Closed;
mComm->Close(packet.node);
}
}
void NetServer::OnDisconnect(NetNode &node, const NetPacket &packet)
{
if (node.Status == NodeStatus::InGame)
{
Printf("Player %d left the server", node.Player);
playeringame[node.Player] = false;
players[node.Player].settings_controller = false;
node.Player = -1;
}
node.Status = NodeStatus::Closed;
mComm->Close(packet.node);
}
void NetServer::OnTic(NetNode &node, const NetPacket &packet)
{
if (node.Status == NodeStatus::InGame)
{
if (packet.size != 2 + sizeof(usercmd_t))
return;
memcpy(&mCurrentInput[node.Player].ucmd, &packet[2], sizeof(usercmd_t));
}
else
{
node.Status = NodeStatus::Closed;
mComm->Close(packet.node);
}
}

93
src/d_netserver.h Normal file
View file

@ -0,0 +1,93 @@
//-----------------------------------------------------------------------------
//
// Copyright 1993-1996 id Software
// Copyright 1999-2016 Randy Heit
// Copyright 2002-2016 Christoph Oelckers
// Copyright 2018 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
#pragma once
#include "d_net.h"
enum class NetPacketType
{
ConnectRequest,
ConnectResponse,
Disconnect,
Tic
};
enum class NodeStatus
{
Closed,
InPreGame,
InGame
};
struct NetNode
{
NodeStatus Status = NodeStatus::Closed;
int Ping = 0;
int Gametic = 0;
int Player = -1;
ticcmd_t PlayerMovement;
FDynamicBuffer Commands; // "NetSpecs"
};
class NetServer : public Network
{
public:
NetServer();
void Update() override;
void SetCurrentTic(int receivetic, int sendtic) override;
void EndCurrentTic() override;
int GetSendTick() const override;
ticcmd_t GetPlayerInput(int player) const override;
ticcmd_t GetSentInput(int tic) const override;
void RunCommands(int player) override;
void WriteLocalInput(ticcmd_t cmd) override;
void WriteBotInput(int player, const ticcmd_t &cmd) override;
void WriteBytes(const uint8_t *block, int len) override;
int GetPing(int player) const override;
int GetServerPing() const override;
void ListPingTimes() override;
void Network_Controller(int playernum, bool add) override;
private:
void OnClose(NetNode &node, const NetPacket &packet);
void OnConnectRequest(NetNode &node, const NetPacket &packet);
void OnDisconnect(NetNode &node, const NetPacket &packet);
void OnTic(NetNode &node, const NetPacket &packet);
std::unique_ptr<doomcom_t> mComm;
NetNode mNodes[MAXNETNODES];
int mNodeForPlayer[MAXPLAYERS];
int mSendTic = 0;
ticcmd_t mCurrentInput[MAXPLAYERS];
FDynamicBuffer mCurrentCommands;
FDynamicBuffer mSendCommands;
};

151
src/d_netsingle.cpp Normal file
View file

@ -0,0 +1,151 @@
//-----------------------------------------------------------------------------
//
// Copyright 1993-1996 id Software
// Copyright 1999-2016 Randy Heit
// Copyright 2002-2016 Christoph Oelckers
// Copyright 2018 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
#include <stddef.h>
#include <inttypes.h>
#include "version.h"
#include "menu/menu.h"
#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"
#include "d_netsingle.h"
#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"
#include "p_trace.h"
#include "a_sharedglobal.h"
#include "st_start.h"
#include "teaminfo.h"
#include "p_conversation.h"
#include "g_level.h"
#include "d_event.h"
#include "m_argv.h"
#include "p_lnspec.h"
#include "v_video.h"
#include "p_spec.h"
#include "hardware.h"
#include "r_utility.h"
#include "a_keys.h"
#include "intermission/intermission.h"
#include "g_levellocals.h"
#include "events.h"
#include "i_time.h"
extern bool netserver, netclient;
NetSinglePlayer::NetSinglePlayer()
{
netgame = false;
netclient = false;
netserver = false;
multiplayer = false;
consoleplayer = 0;
players[0].settings_controller = true;
playeringame[0] = true;
}
void NetSinglePlayer::Update()
{
}
void NetSinglePlayer::SetCurrentTic(int receivetic, int sendtic)
{
gametic = receivetic;
mSendTic = sendtic;
}
void NetSinglePlayer::EndCurrentTic()
{
mCurrentCommands = mSendCommands;
mSendCommands.Clear();
}
int NetSinglePlayer::GetSendTick() const
{
return mSendTic;
}
ticcmd_t NetSinglePlayer::GetPlayerInput(int player) const
{
return mCurrentInput[player];
}
ticcmd_t NetSinglePlayer::GetSentInput(int tic) const
{
return mCurrentInput[consoleplayer];
}
void NetSinglePlayer::RunCommands(int player)
{
if (player == consoleplayer)
{
Net_RunCommands(mCurrentCommands, consoleplayer);
}
}
void NetSinglePlayer::WriteLocalInput(ticcmd_t cmd)
{
mCurrentInput[consoleplayer] = cmd;
}
void NetSinglePlayer::WriteBotInput(int player, const ticcmd_t &cmd)
{
mCurrentInput[player] = cmd;
}
void NetSinglePlayer::WriteBytes(const uint8_t *block, int len)
{
mSendCommands.AppendData(block, len);
}
int NetSinglePlayer::GetPing(int player) const
{
return 0;
}
int NetSinglePlayer::GetServerPing() const
{
return 0;
}
void NetSinglePlayer::ListPingTimes()
{
}
void NetSinglePlayer::Network_Controller(int playernum, bool add)
{
}

58
src/d_netsingle.h Normal file
View file

@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
//
// Copyright 1993-1996 id Software
// Copyright 1999-2016 Randy Heit
// Copyright 2002-2016 Christoph Oelckers
// Copyright 2018 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
#pragma once
#include "d_net.h"
class NetSinglePlayer : public Network
{
public:
NetSinglePlayer();
void Update() override;
void SetCurrentTic(int receivetic, int sendtic) override;
void EndCurrentTic() override;
int GetSendTick() const override;
ticcmd_t GetPlayerInput(int player) const override;
ticcmd_t GetSentInput(int tic) const override;
void RunCommands(int player) override;
void WriteLocalInput(ticcmd_t cmd) override;
void WriteBotInput(int player, const ticcmd_t &cmd) override;
void WriteBytes(const uint8_t *block, int len) override;
int GetPing(int player) const override;
int GetServerPing() const override;
void ListPingTimes() override;
void Network_Controller(int playernum, bool add) override;
private:
ticcmd_t mCurrentInput[MAXPLAYERS];
FDynamicBuffer mCurrentCommands;
int mSendTic = 0;
FDynamicBuffer mSendCommands;
};

33
src/d_netsync.h Normal file
View file

@ -0,0 +1,33 @@
#ifndef __D_NETSYNC_H__
#define __D_NETSYNC_H__
struct NetSyncData {
DVector3 Pos;
DVector3 Vel;
DAngle SpriteAngle;
DAngle SpriteRotation;
DRotator Angles;
DVector2 Scale; // Scaling values; 1 is normal size
double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double.
int sprite; // used to find patch_t and flip value
uint8_t frame; // sprite frame to draw
uint8_t effects; // [RH] see p_effect.h
FRenderStyle RenderStyle; // Style to draw this actor with
uint32_t Translation;
uint32_t RenderRequired; // current renderer must have this feature set
uint32_t RenderHidden; // current renderer must *not* have any of these features
uint32_t renderflags; // Different rendering flags
double Floorclip; // value to use for floor clipping
DAngle VisibleStartAngle;
DAngle VisibleStartPitch;
DAngle VisibleEndAngle;
DAngle VisibleEndPitch;
double Speed;
double FloatSpeed;
double CameraHeight; // Height of camera when used as such
double CameraFOV;
double StealthAlpha; // Minmum alpha for MF_STEALTH.
};
#endif //__D_NETSYNC_H__

View file

@ -290,7 +290,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, ticcmd_t &cmd, ticcmd_
{
if (arc.BeginObject(key))
{
arc("consistency", cmd.consistancy)
arc("consistency", cmd.consistency)
("ucmd", cmd.ucmd)
.EndObject();
}
@ -360,7 +360,7 @@ int SkipTicCmd (uint8_t **stream, int count)
{
bool moreticdata = true;
flow += 2; // Skip consistancy marker
flow += 2; // Skip consistency marker
while (moreticdata)
{
uint8_t type = *flow++;
@ -407,68 +407,6 @@ int SkipTicCmd (uint8_t **stream, int count)
return skip;
}
extern short consistancy[MAXPLAYERS][BACKUPTICS];
void ReadTicCmd (uint8_t **stream, int player, int tic)
{
int type;
uint8_t *start;
ticcmd_t *tcmd;
int ticmod = tic % BACKUPTICS;
tcmd = &netcmds[player][ticmod];
tcmd->consistancy = ReadWord (stream);
start = *stream;
while ((type = ReadByte (stream)) != DEM_USERCMD && type != DEM_EMPTYUSERCMD)
Net_SkipCommand (type, stream);
NetSpecs[player][ticmod].SetData (start, int(*stream - start - 1));
if (type == DEM_USERCMD)
{
UnpackUserCmd (&tcmd->ucmd,
tic ? &netcmds[player][(tic-1)%BACKUPTICS].ucmd : NULL, stream);
}
else
{
if (tic)
{
memcpy (&tcmd->ucmd, &netcmds[player][(tic-1)%BACKUPTICS].ucmd, sizeof(tcmd->ucmd));
}
else
{
memset (&tcmd->ucmd, 0, sizeof(tcmd->ucmd));
}
}
if (player==consoleplayer&&tic>BACKUPTICS)
assert(consistancy[player][ticmod] == tcmd->consistancy);
}
void RunNetSpecs (int player, int buf)
{
uint8_t *stream;
int len;
if (gametic % ticdup == 0)
{
stream = NetSpecs[player][buf].GetData (&len);
if (stream)
{
uint8_t *end = stream + len;
while (stream < end)
{
int type = ReadByte (&stream);
Net_DoCommand (type, &stream, player);
}
if (!demorecording)
NetSpecs[player][buf].SetData (NULL, 0);
}
}
}
uint8_t *lenspot;
// Write the header of an IFF chunk and leave space

View file

@ -63,13 +63,13 @@ struct zdemoheader_s {
struct usercmd_t
{
uint32_t buttons;
short pitch; // up/down
short yaw; // left/right
short roll; // "tilt"
short forwardmove;
short sidemove;
short upmove;
uint32_t buttons = 0;
short pitch = 0; // up/down
short yaw = 0; // left/right
short roll = 0; // "tilt"
short forwardmove = 0;
short sidemove = 0;
short upmove = 0;
};
// When transmitted, the above message is preceded by a byte
@ -238,12 +238,10 @@ int WriteUserCmdMessage (usercmd_t *ucmd, const usercmd_t *basis, uint8_t **stre
struct ticcmd_t
{
usercmd_t ucmd;
int16_t consistancy; // checks for net game
int16_t consistency = 0; // checks for net game
};
int SkipTicCmd (uint8_t **stream, int count);
void ReadTicCmd (uint8_t **stream, int player, int tic);
void RunNetSpecs (int player, int buf);
int ReadByte (uint8_t **stream);
int ReadWord (uint8_t **stream);

View file

@ -79,6 +79,9 @@ extern bool multiplayer;
// [SP] Map dm/coop implementation - invokes fake multiplayer without bots
extern bool multiplayernext;
// clientside playsim
extern bool netclient;
// Flag: true only if started as net deathmatch.
EXTERN_CVAR (Int, deathmatch)

View file

@ -153,13 +153,13 @@ bool E_SendNetworkEvent(FString name, int arg1, int arg2, int arg3, bool manual)
if (gamestate != GS_LEVEL)
return false;
Net_WriteByte(DEM_NETEVENT);
Net_WriteString(name);
Net_WriteByte(3);
Net_WriteLong(arg1);
Net_WriteLong(arg2);
Net_WriteLong(arg3);
Net_WriteByte(manual);
network->WriteByte(DEM_NETEVENT);
network->WriteString(name);
network->WriteByte(3);
network->WriteLong(arg1);
network->WriteLong(arg2);
network->WriteLong(arg3);
network->WriteByte(manual);
return true;
}

View file

@ -77,6 +77,7 @@
#include "g_hub.h"
#include "g_levellocals.h"
#include "events.h"
#include "gameconfigfile.h"
static FRandom pr_dmspawn ("DMSpawn");
@ -84,7 +85,7 @@ static FRandom pr_pspawn ("PlayerSpawn");
bool G_CheckDemoStatus (void);
void G_ReadDemoTiccmd (ticcmd_t *cmd, int player);
void G_WriteDemoTiccmd (ticcmd_t *cmd, int player, int buf);
void G_WriteDemoTiccmd (ticcmd_t *cmd, int player);
void G_PlayerReborn (int player);
void G_DoNewGame (void);
@ -149,6 +150,8 @@ bool viewactive;
bool netgame; // only true if packets are broadcast
bool multiplayer;
bool multiplayernext = false; // [SP] Map coop/dm implementation
bool netclient; // clientside playsim
bool netserver = false; // used to enforce 'netplay = true'
player_t players[MAXPLAYERS];
bool playeringame[MAXPLAYERS];
@ -176,9 +179,6 @@ bool precache = true; // if true, load all graphics at start
wbstartstruct_t wminfo; // parms for world map / intermission
short consistancy[MAXPLAYERS][BACKUPTICS];
#define MAXPLMOVE (forwardmove[1])
#define TURBOTHRESHOLD 12800
@ -296,12 +296,12 @@ CCMD (slot)
CCMD (centerview)
{
Net_WriteByte (DEM_CENTERVIEW);
network->WriteByte (DEM_CENTERVIEW);
}
CCMD(crouch)
{
Net_WriteByte(DEM_CROUCH);
network->WriteByte(DEM_CROUCH);
}
CCMD (land)
@ -544,7 +544,7 @@ static inline int joyint(double val)
// or reads it from the demo buffer.
// If recording a demo, write it out
//
void G_BuildTiccmd (ticcmd_t *cmd)
ticcmd_t G_BuildTiccmd ()
{
int strafe;
int speed;
@ -552,12 +552,9 @@ void G_BuildTiccmd (ticcmd_t *cmd)
int side;
int fly;
ticcmd_t *base;
ticcmd_t cmd;
base = I_BaseTiccmd (); // empty, or external driver
*cmd = *base;
cmd->consistancy = consistancy[consoleplayer][(maketic/ticdup)%BACKUPTICS];
cmd.consistency = network->GetConsoleConsistency();
strafe = Button_Strafe.bDown;
speed = Button_Speed.bDown ^ (int)cl_run;
@ -568,7 +565,7 @@ void G_BuildTiccmd (ticcmd_t *cmd)
// and not the joystick, since we treat the joystick as
// the analog device it is.
if (Button_Left.bDown || Button_Right.bDown)
turnheld += ticdup;
turnheld += network->ticdup;
else
turnheld = 0;
@ -632,32 +629,32 @@ void G_BuildTiccmd (ticcmd_t *cmd)
side -= sidemove[speed];
// buttons
if (Button_Attack.bDown) cmd->ucmd.buttons |= BT_ATTACK;
if (Button_AltAttack.bDown) cmd->ucmd.buttons |= BT_ALTATTACK;
if (Button_Use.bDown) cmd->ucmd.buttons |= BT_USE;
if (Button_Jump.bDown) cmd->ucmd.buttons |= BT_JUMP;
if (Button_Crouch.bDown) cmd->ucmd.buttons |= BT_CROUCH;
if (Button_Zoom.bDown) cmd->ucmd.buttons |= BT_ZOOM;
if (Button_Reload.bDown) cmd->ucmd.buttons |= BT_RELOAD;
if (Button_Attack.bDown) cmd.ucmd.buttons |= BT_ATTACK;
if (Button_AltAttack.bDown) cmd.ucmd.buttons |= BT_ALTATTACK;
if (Button_Use.bDown) cmd.ucmd.buttons |= BT_USE;
if (Button_Jump.bDown) cmd.ucmd.buttons |= BT_JUMP;
if (Button_Crouch.bDown) cmd.ucmd.buttons |= BT_CROUCH;
if (Button_Zoom.bDown) cmd.ucmd.buttons |= BT_ZOOM;
if (Button_Reload.bDown) cmd.ucmd.buttons |= BT_RELOAD;
if (Button_User1.bDown) cmd->ucmd.buttons |= BT_USER1;
if (Button_User2.bDown) cmd->ucmd.buttons |= BT_USER2;
if (Button_User3.bDown) cmd->ucmd.buttons |= BT_USER3;
if (Button_User4.bDown) cmd->ucmd.buttons |= BT_USER4;
if (Button_User1.bDown) cmd.ucmd.buttons |= BT_USER1;
if (Button_User2.bDown) cmd.ucmd.buttons |= BT_USER2;
if (Button_User3.bDown) cmd.ucmd.buttons |= BT_USER3;
if (Button_User4.bDown) cmd.ucmd.buttons |= BT_USER4;
if (Button_Speed.bDown) cmd->ucmd.buttons |= BT_SPEED;
if (Button_Strafe.bDown) cmd->ucmd.buttons |= BT_STRAFE;
if (Button_MoveRight.bDown) cmd->ucmd.buttons |= BT_MOVERIGHT;
if (Button_MoveLeft.bDown) cmd->ucmd.buttons |= BT_MOVELEFT;
if (Button_LookDown.bDown) cmd->ucmd.buttons |= BT_LOOKDOWN;
if (Button_LookUp.bDown) cmd->ucmd.buttons |= BT_LOOKUP;
if (Button_Back.bDown) cmd->ucmd.buttons |= BT_BACK;
if (Button_Forward.bDown) cmd->ucmd.buttons |= BT_FORWARD;
if (Button_Right.bDown) cmd->ucmd.buttons |= BT_RIGHT;
if (Button_Left.bDown) cmd->ucmd.buttons |= BT_LEFT;
if (Button_MoveDown.bDown) cmd->ucmd.buttons |= BT_MOVEDOWN;
if (Button_MoveUp.bDown) cmd->ucmd.buttons |= BT_MOVEUP;
if (Button_ShowScores.bDown) cmd->ucmd.buttons |= BT_SHOWSCORES;
if (Button_Speed.bDown) cmd.ucmd.buttons |= BT_SPEED;
if (Button_Strafe.bDown) cmd.ucmd.buttons |= BT_STRAFE;
if (Button_MoveRight.bDown) cmd.ucmd.buttons |= BT_MOVERIGHT;
if (Button_MoveLeft.bDown) cmd.ucmd.buttons |= BT_MOVELEFT;
if (Button_LookDown.bDown) cmd.ucmd.buttons |= BT_LOOKDOWN;
if (Button_LookUp.bDown) cmd.ucmd.buttons |= BT_LOOKUP;
if (Button_Back.bDown) cmd.ucmd.buttons |= BT_BACK;
if (Button_Forward.bDown) cmd.ucmd.buttons |= BT_FORWARD;
if (Button_Right.bDown) cmd.ucmd.buttons |= BT_RIGHT;
if (Button_Left.bDown) cmd.ucmd.buttons |= BT_LEFT;
if (Button_MoveDown.bDown) cmd.ucmd.buttons |= BT_MOVEDOWN;
if (Button_MoveUp.bDown) cmd.ucmd.buttons |= BT_MOVEUP;
if (Button_ShowScores.bDown) cmd.ucmd.buttons |= BT_SHOWSCORES;
// Handle joysticks/game controllers.
float joyaxes[NUM_JOYAXIS];
@ -695,7 +692,7 @@ void G_BuildTiccmd (ticcmd_t *cmd)
forward += (int)((float)mousey * m_forward);
}
cmd->ucmd.pitch = LocalViewPitch >> 16;
cmd.ucmd.pitch = LocalViewPitch >> 16;
if (SendLand)
{
@ -718,10 +715,10 @@ void G_BuildTiccmd (ticcmd_t *cmd)
else if (side < -MAXPLMOVE)
side = -MAXPLMOVE;
cmd->ucmd.forwardmove += forward;
cmd->ucmd.sidemove += side;
cmd->ucmd.yaw = LocalViewAngle >> 16;
cmd->ucmd.upmove = fly;
cmd.ucmd.forwardmove += forward;
cmd.ucmd.sidemove += side;
cmd.ucmd.yaw = LocalViewAngle >> 16;
cmd.ucmd.upmove = fly;
LocalViewAngle = 0;
LocalViewPitch = 0;
@ -729,42 +726,44 @@ void G_BuildTiccmd (ticcmd_t *cmd)
if (sendturn180)
{
sendturn180 = false;
cmd->ucmd.buttons |= BT_TURN180;
cmd.ucmd.buttons |= BT_TURN180;
}
if (sendpause)
{
sendpause = false;
Net_WriteByte (DEM_PAUSE);
network->WriteByte (DEM_PAUSE);
}
if (sendsave)
{
sendsave = false;
Net_WriteByte (DEM_SAVEGAME);
Net_WriteString (savegamefile);
Net_WriteString (savedescription);
network->WriteByte (DEM_SAVEGAME);
network->WriteString (savegamefile);
network->WriteString (savedescription);
savegamefile = "";
}
if (SendItemUse == (const AInventory *)1)
{
Net_WriteByte (DEM_INVUSEALL);
network->WriteByte (DEM_INVUSEALL);
SendItemUse = NULL;
}
else if (SendItemUse != NULL)
{
Net_WriteByte (DEM_INVUSE);
Net_WriteLong (SendItemUse->InventoryID);
network->WriteByte (DEM_INVUSE);
network->WriteLong (SendItemUse->InventoryID);
SendItemUse = NULL;
}
if (SendItemDrop != NULL)
{
Net_WriteByte (DEM_INVDROP);
Net_WriteLong (SendItemDrop->InventoryID);
Net_WriteLong(SendItemDropAmount);
network->WriteByte (DEM_INVDROP);
network->WriteLong (SendItemDrop->InventoryID);
network->WriteLong(SendItemDropAmount);
SendItemDrop = NULL;
}
cmd->ucmd.forwardmove <<= 8;
cmd->ucmd.sidemove <<= 8;
cmd.ucmd.forwardmove <<= 8;
cmd.ucmd.sidemove <<= 8;
return cmd;
}
//[Graf Zahl] This really helps if the mouse update rate can't be increased!
@ -863,7 +862,7 @@ static void ChangeSpy (int changespy)
// has done this for you, since it could desync otherwise.
if (!demoplayback)
{
Net_WriteByte(DEM_REVERTCAMERA);
network->WriteByte(DEM_REVERTCAMERA);
}
return;
}
@ -1132,10 +1131,7 @@ void G_Ticker ()
}
}
// get commands, check consistancy, and build new consistancy check
int buf = (gametic/ticdup)%BACKUPTICS;
// [RH] Include some random seeds and player stuff in the consistancy
// [RH] Include some random seeds and player stuff in the consistency
// check, not just the player's x position like BOOM.
uint32_t rngsum = FRandom::StaticSumSeeds ();
@ -1147,15 +1143,13 @@ void G_Ticker ()
if (playeringame[i])
{
ticcmd_t *cmd = &players[i].cmd;
ticcmd_t *newcmd = &netcmds[i][buf];
ticcmd_t newcmd = network->GetPlayerInput(i);
network->RunCommands(i);
if ((gametic % ticdup) == 0)
{
RunNetSpecs (i, buf);
}
if (demorecording)
{
G_WriteDemoTiccmd (newcmd, i, buf);
G_WriteDemoTiccmd (&newcmd, i);
}
players[i].oldbuttons = cmd->ucmd.buttons;
// If the user alt-tabbed away, paused gets set to -1. In this case,
@ -1167,7 +1161,7 @@ void G_Ticker ()
}
else
{
memcpy(cmd, newcmd, sizeof(ticcmd_t));
*cmd = newcmd;
}
// check for turbo cheats
@ -1177,22 +1171,21 @@ void G_Ticker ()
Printf ("%s is turbo!\n", players[i].userinfo.GetName());
}
if (netgame && players[i].Bot == NULL && !demoplayback && (gametic%ticdup) == 0)
if (netgame && players[i].Bot == NULL && !demoplayback && (gametic%network->ticdup) == 0)
{
//players[i].inconsistant = 0;
if (gametic > BACKUPTICS*ticdup && consistancy[i][buf] != cmd->consistancy)
if (network->IsInconsistent(i, cmd->consistency))
{
players[i].inconsistant = gametic - BACKUPTICS*ticdup;
players[i].inconsistant = gametic - BACKUPTICS*network->ticdup;
}
if (players[i].mo)
{
uint32_t sum = rngsum + int((players[i].mo->X() + players[i].mo->Y() + players[i].mo->Z())*257) + players[i].mo->Angles.Yaw.BAMs() + players[i].mo->Angles.Pitch.BAMs();
sum ^= players[i].health;
consistancy[i][buf] = sum;
network->SetConsistency(i, sum);
}
else
{
consistancy[i][buf] = rngsum;
network->SetConsistency(i, rngsum);
}
}
}
@ -2439,11 +2432,8 @@ CCMD (stop)
extern uint8_t *lenspot;
void G_WriteDemoTiccmd (ticcmd_t *cmd, int player, int buf)
void G_WriteDemoTiccmd (ticcmd_t *cmd, int player)
{
uint8_t *specdata;
int speclen;
if (stoprecording)
{ // use "stop" console command to end demo recording
G_CheckDemoStatus ();
@ -2455,12 +2445,7 @@ void G_WriteDemoTiccmd (ticcmd_t *cmd, int player, int buf)
}
// [RH] Write any special "ticcmds" for this player to the demo
if ((specdata = NetSpecs[player][buf].GetData (&speclen)) && gametic % ticdup == 0)
{
memcpy (demo_p, specdata, speclen);
demo_p += speclen;
NetSpecs[player][buf].SetData (NULL, 0);
}
demo_p += network->CopySpecData(player, demo_p, maxdemosize - (demo_p - demobuffer));
// [RH] Now write out a "normal" ticcmd.
WriteUserCmdMessage (&cmd->ucmd, &players[player].cmd.ucmd, &demo_p);
@ -2861,6 +2846,62 @@ void G_TimeDemo (const char* name)
gameaction = (gameaction == ga_loadgame) ? ga_loadgameplaydemo : ga_playdemo;
}
void G_InitServerNetGame(const char *mapname)
{
netgame = true;
netserver = true;
netclient = false;
multiplayer = true;
multiplayernext = true;
consoleplayer = 0;
players[consoleplayer].settings_controller = true;
playeringame[consoleplayer] = true;
GameConfig->ReadNetVars(); // [RH] Read network ServerInfo cvars
D_SetupUserInfo();
G_DeferedInitNew(mapname);
}
void G_InitClientNetGame(int player, const char* mapname)
{
netgame = true;
netserver = false;
netclient = true;
multiplayer = true;
multiplayernext = true;
consoleplayer = player;
players[consoleplayer].settings_controller = true;
playeringame[consoleplayer] = true;
GameConfig->ReadNetVars(); // [RH] Read network ServerInfo cvars
D_SetupUserInfo();
G_DeferedInitNew(mapname);
}
void G_EndNetGame()
{
gameaction = ga_fullconsole;
// Should we do this?
//C_RestoreCVars(); // Is this a good idea?
P_SetupWeapons_ntohton();
demoplayback = false;
netgame = false;
netclient = false;
multiplayer = false;
multiplayernext = false;
for (int i = 1; i < MAXPLAYERS; i++)
playeringame[i] = 0;
consoleplayer = 0;
players[0].camera = NULL;
if (StatusBar != NULL)
{
StatusBar->AttachToPlayer(&players[0]);
}
}
/*
===================

View file

@ -63,6 +63,10 @@ void G_PlayDemo (char* name);
void G_TimeDemo (const char* name);
bool G_CheckDemoStatus (void);
void G_InitServerNetGame(const char *mapname);
void G_InitClientNetGame(int player, const char* mapname);
void G_EndNetGame();
void G_WorldDone (void);
void G_Ticker (void);

View file

@ -1103,15 +1103,15 @@ void FWeaponSlots::SendDifferences(int playernum, const FWeaponSlots &other)
// The slots differ. Send mine.
if (playernum == consoleplayer)
{
Net_WriteByte(DEM_SETSLOT);
network->WriteByte(DEM_SETSLOT);
}
else
{
Net_WriteByte(DEM_SETSLOTPNUM);
Net_WriteByte(playernum);
network->WriteByte(DEM_SETSLOTPNUM);
network->WriteByte(playernum);
}
Net_WriteByte(i);
Net_WriteByte(Slots[i].Size());
network->WriteByte(i);
network->WriteByte(Slots[i].Size());
for (j = 0; j < Slots[i].Size(); ++j)
{
Net_WriteWeapon(Slots[i].GetWeapon(j));
@ -1241,9 +1241,9 @@ CCMD (setslot)
Printf ("Slot %d cleared\n", slot);
}
Net_WriteByte(DEM_SETSLOT);
Net_WriteByte(slot);
Net_WriteByte(argv.argc()-2);
network->WriteByte(DEM_SETSLOT);
network->WriteByte(slot);
network->WriteByte(argv.argc()-2);
for (int i = 2; i < argv.argc(); i++)
{
Net_WriteWeapon(PClass::FindActor(argv[i]));
@ -1292,8 +1292,8 @@ CCMD (addslot)
}
else
{
Net_WriteByte(DEM_ADDSLOT);
Net_WriteByte(slot);
network->WriteByte(DEM_ADDSLOT);
network->WriteByte(slot);
Net_WriteWeapon(type);
}
}
@ -1368,8 +1368,8 @@ CCMD (addslotdefault)
}
else
{
Net_WriteByte(DEM_ADDSLOTDEFAULT);
Net_WriteByte(slot);
network->WriteByte(DEM_ADDSLOTDEFAULT);
network->WriteByte(slot);
Net_WriteWeapon(type);
}
}
@ -1440,7 +1440,7 @@ void P_SetupWeapons_ntohton()
// for any game appear second, and weapons that filter for some other game
// appear last. The idea here is to try to keep all the weapons that are
// most likely to be used at the start of the list so that they only need
// one byte to transmit across the network.
// one byte to transmit across the network->
//
//===========================================================================
@ -1534,12 +1534,12 @@ void Net_WriteWeapon(PClassActor *type)
assert(index >= 0 && index <= 32767);
if (index < 128)
{
Net_WriteByte(index);
network->WriteByte(index);
}
else
{
Net_WriteByte(0x80 | index);
Net_WriteByte(index >> 7);
network->WriteByte(0x80 | index);
network->WriteByte(index >> 7);
}
}

View file

@ -150,6 +150,8 @@ extern bool sendpause, sendsave, sendturn180, SendLand;
void *statcopy; // for statistics driver
FLevelLocals level; // info about current level
extern bool netserver; // serverside playsim
extern bool netclient; // clientside playsim
//==========================================================================
@ -350,7 +352,7 @@ void G_NewInit ()
}
G_ClearSnapshots ();
netgame = false;
netgame = (netclient || netserver);
multiplayer = multiplayernext;
multiplayernext = false;
if (demoplayback)
@ -903,7 +905,7 @@ IMPLEMENT_CLASS(DAutosaver, false, false)
void DAutosaver::Tick ()
{
Net_WriteByte (DEM_CHECKAUTOSAVE);
network->WriteByte (DEM_CHECKAUTOSAVE);
Destroy ();
}

View file

@ -695,8 +695,8 @@ CCMD (spray)
return;
}
Net_WriteByte (DEM_SPRAY);
Net_WriteString (argv[1]);
network->WriteByte (DEM_SPRAY);
network->WriteString (argv[1]);
}
void SprayDecal(AActor *shooter, const char *name, double distance)

View file

@ -1051,11 +1051,8 @@ static void DrawLatency()
{
return;
}
int i, localdelay = 0, arbitratordelay = 0;
for (i = 0; i < BACKUPTICS; i++) localdelay += netdelay[0][i];
for (i = 0; i < BACKUPTICS; i++) arbitratordelay += netdelay[nodeforplayer[Net_Arbitrator]][i];
localdelay = ((localdelay / BACKUPTICS) * ticdup) * (1000 / TICRATE);
arbitratordelay = ((arbitratordelay / BACKUPTICS) * ticdup) * (1000 / TICRATE);
int localdelay = network->GetPing(0);
int arbitratordelay = network->GetServerPing();
int color = CR_GREEN;
if (MAX(localdelay, arbitratordelay) > 200)
{
@ -1065,7 +1062,7 @@ static void DrawLatency()
{
color = CR_ORANGE;
}
if (MAX(localdelay, arbitratordelay) >= ((BACKUPTICS / 2 - 1) * ticdup) * (1000 / TICRATE))
if (MAX(localdelay, arbitratordelay) >= network->GetHighPingThreshold())
{
color = CR_RED;
}

View file

@ -1214,7 +1214,7 @@ void DBaseStatusBar::DrawConsistancy () const
{
fprintf (debugfile, "%s as of tic %d (%d)\n", conbuff,
players[1-consoleplayer].inconsistant,
players[1-consoleplayer].inconsistant/ticdup);
players[1-consoleplayer].inconsistant/network->ticdup);
}
}
screen->DrawText (SmallFont, CR_GREEN,

View file

@ -404,7 +404,7 @@ static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2,
{
// The teamplay mode uses colors to show teams, so we need some
// other way to do highlighting. And it may as well be used for
// all modes for the sake of consistancy.
// all modes for the sake of consistency.
screen->Dim(MAKERGB(200,245,255), 0.125f, col1 - 12*CleanXfac, y - 1, col5 + (maxnamewidth + 24)*CleanXfac, height + 2);
}
@ -431,14 +431,7 @@ static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2,
screen->DrawText (SmallFont, color, col4, y + ypadding, player->userinfo.GetName(),
DTA_CleanNoMove, true, TAG_DONE);
int avgdelay = 0;
for (int i = 0; i < BACKUPTICS; i++)
{
avgdelay += netdelay[nodeforplayer[(int)(player - players)]][i];
}
avgdelay /= BACKUPTICS;
mysnprintf(str, countof(str), "%d", (avgdelay * ticdup) * (1000 / TICRATE));
mysnprintf(str, countof(str), "%d", network->GetPing((int)(player - players)));
screen->DrawText(SmallFont, color, col5, y + ypadding, str,
DTA_CleanNoMove, true, TAG_DONE);

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,38 @@
#ifndef __I_NET_H__
#define __I_NET_H__
// Called by D_DoomMain.
bool I_InitNetwork (void);
void I_NetCmd (void);
#pragma once
#endif
#include <memory>
#define MAX_MSGLEN 14000
#define DOOMPORT 5029
struct NetPacket
{
NetPacket() { memset(data, 0, sizeof(data)); }
// packet data to be sent
uint8_t data[MAX_MSGLEN];
// bytes in data to be sent
int16_t size = 0;
// dest for send, set by get (-1 = no packet).
int16_t node = 0;
uint8_t &operator[](int i) { return data[i]; }
const uint8_t &operator[](int i) const { return data[i]; }
};
// Network packet data.
struct doomcom_t
{
virtual ~doomcom_t() { }
virtual void PacketSend(const NetPacket &packet) = 0;
virtual void PacketGet(NetPacket &packet) = 0;
virtual int Connect(const char *name) = 0;
virtual void Close(int node) = 0;
};
std::unique_ptr<doomcom_t> I_InitNetwork(int port);

View file

@ -587,17 +587,17 @@ static void SummonActor (int command, int command2, FCommandLine argv)
Printf ("Unknown actor '%s'\n", argv[1]);
return;
}
Net_WriteByte (argv.argc() > 2 ? command2 : command);
Net_WriteString (type->TypeName.GetChars());
network->WriteByte (argv.argc() > 2 ? command2 : command);
network->WriteString (type->TypeName.GetChars());
if (argv.argc () > 2)
{
Net_WriteWord (atoi (argv[2])); // angle
Net_WriteWord ((argv.argc() > 3) ? atoi(argv[3]) : 0); // TID
Net_WriteByte ((argv.argc() > 4) ? atoi(argv[4]) : 0); // special
network->WriteWord (atoi (argv[2])); // angle
network->WriteWord ((argv.argc() > 3) ? atoi(argv[3]) : 0); // TID
network->WriteByte ((argv.argc() > 4) ? atoi(argv[4]) : 0); // special
for (int i = 5; i < 10; i++)
{ // args[5]
Net_WriteLong((i < argv.argc()) ? atoi(argv[i]) : 0);
network->WriteLong((i < argv.argc()) ? atoi(argv[i]) : 0);
}
}
}

View file

@ -761,7 +761,7 @@ bool DIntermissionController::Responder (event_t *ev)
int res = mScreen->Responder(ev);
if (res == -1 && !mSentAdvance)
{
Net_WriteByte(DEM_ADVANCEINTER);
network->WriteByte(DEM_ADVANCEINTER);
mSentAdvance = true;
}
return !!res;

View file

@ -689,6 +689,6 @@ CCMD (mdk)
return;
const char *name = argv.argc() > 1 ? argv[1] : "";
Net_WriteByte (DEM_MDK);
Net_WriteString(name);
network->WriteByte (DEM_MDK);
network->WriteString(name);
}

View file

@ -267,7 +267,7 @@ void FRandom::Init(uint32_t seed)
//
// FRandom :: StaticSumSeeds
//
// This function produces a uint32_t that can be used to check the consistancy
// This function produces a uint32_t that can be used to check the consistency
// of network games between different machines. Only a select few RNGs are
// used for the sum, because not all RNGs are important to network sync.
//

View file

@ -695,17 +695,17 @@ DEFINE_ACTION_FUNCTION(DConversationMenu, SendConversationReply)
switch (node)
{
case -1:
Net_WriteByte(DEM_CONVNULL);
network->WriteByte(DEM_CONVNULL);
break;
case -2:
Net_WriteByte(DEM_CONVCLOSE);
network->WriteByte(DEM_CONVCLOSE);
break;
default:
Net_WriteByte(DEM_CONVREPLY);
Net_WriteWord(node);
Net_WriteByte(reply);
network->WriteByte(DEM_CONVREPLY);
network->WriteWord(node);
network->WriteByte(reply);
break;
}
StaticLastReply = reply;

View file

@ -1987,8 +1987,8 @@ CCMD (kill)
if (CheckCheatmode ())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_MASSACRE);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_MASSACRE);
}
else if (!stricmp (argv[1], "baddies"))
{
@ -1996,13 +1996,13 @@ CCMD (kill)
if (CheckCheatmode ())
return;
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_MASSACRE2);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (CHT_MASSACRE2);
}
else
{
Net_WriteByte (DEM_KILLCLASSCHEAT);
Net_WriteString (argv[1]);
network->WriteByte (DEM_KILLCLASSCHEAT);
network->WriteString (argv[1]);
}
}
else
@ -2012,7 +2012,7 @@ CCMD (kill)
return;
// Kill the player
Net_WriteByte (DEM_SUICIDE);
network->WriteByte (DEM_SUICIDE);
}
C_HideConsole ();
}
@ -2024,8 +2024,8 @@ CCMD(remove)
if (CheckCheatmode())
return;
Net_WriteByte(DEM_REMOVE);
Net_WriteString(argv[1]);
network->WriteByte(DEM_REMOVE);
network->WriteString(argv[1]);
C_HideConsole();
}
else
@ -2033,5 +2033,4 @@ CCMD(remove)
Printf("Usage: remove <actor class name>\n");
return;
}
}

View file

@ -3130,7 +3130,7 @@ FUNC(LS_Autosave)
if (gameaction != ga_savegame)
{
level.flags2 &= ~LEVEL2_NOAUTOSAVEHINT;
Net_WriteByte (DEM_CHECKAUTOSAVE);
network->WriteByte (DEM_CHECKAUTOSAVE);
}
return true;
}

View file

@ -1838,6 +1838,10 @@ void P_SpawnThings (int position)
for (int i=0; i < numthings; i++)
{
// Only spawn the player mobj for the client in a client/server game
if (netclient && (MapThingsConverted[i].info->Type || MapThingsConverted[i].info->Special != SMT_Player1Start + position))
continue;
AActor *actor = SpawnMapThing (i, &MapThingsConverted[i], position);
unsigned *udi = MapThingsUserDataIndex.CheckKey((unsigned)i);
if (udi != NULL)

View file

@ -592,7 +592,7 @@ void player_t::SetFOV(float fov)
{
if (consoleplayer == Net_Arbitrator)
{
Net_WriteByte(DEM_MYFOV);
network->WriteByte(DEM_MYFOV);
}
else
{
@ -602,9 +602,9 @@ void player_t::SetFOV(float fov)
}
else
{
Net_WriteByte(DEM_MYFOV);
network->WriteByte(DEM_MYFOV);
}
Net_WriteFloat(clamp<float>(fov, 5.f, 179.f));
network->WriteFloat(clamp<float>(fov, 5.f, 179.f));
}
}
@ -747,9 +747,9 @@ void player_t::SendPitchLimits() const
uppitch = downpitch = (int)maxviewpitch;
}
Net_WriteByte(DEM_SETPITCHLIMIT);
Net_WriteByte(uppitch);
Net_WriteByte(downpitch);
network->WriteByte(DEM_SETPITCHLIMIT);
network->WriteByte(uppitch);
network->WriteByte(downpitch);
}
}
@ -1038,7 +1038,7 @@ void APlayerPawn::PostBeginPlay()
//
// Sets up the default weapon slots for this player. If this is also the
// local player, determines local modifications and sends those across the
// network. Ignores voodoo dolls.
// network-> Ignores voodoo dolls.
//
//===========================================================================
@ -2451,8 +2451,6 @@ nodetype *RestoreNodeList(AActor *act, nodetype *head, nodetype *linktype::*othe
void P_PredictPlayer (player_t *player)
{
int maxtic;
if (cl_noprediction ||
singletics ||
demoplayback ||
@ -2466,7 +2464,7 @@ void P_PredictPlayer (player_t *player)
return;
}
maxtic = maketic;
int maxtic = network->GetSendTick();
if (gametic == maxtic)
{
@ -2517,13 +2515,13 @@ void P_PredictPlayer (player_t *player)
act->BlockNode = NULL;
// Values too small to be usable for lerping can be considered "off".
bool CanLerp = (!(cl_predict_lerpscale < 0.01f) && (ticdup == 1)), DoLerp = false, NoInterpolateOld = R_GetViewInterpolationStatus();
bool CanLerp = (!(cl_predict_lerpscale < 0.01f) && (network->ticdup == 1)), DoLerp = false, NoInterpolateOld = R_GetViewInterpolationStatus();
for (int i = gametic; i < maxtic; ++i)
{
if (!NoInterpolateOld)
R_RebuildViewInterpolation(player);
player->cmd = localcmds[i % LOCALCMDTICS];
player->cmd = network->GetSentInput(i);
P_PlayerThink (player);
player->mo->Tick ();
@ -2590,6 +2588,7 @@ void P_UnPredictPlayer ()
int inventorytics = player->inventorytics;
*player = PredictionPlayerBackup;
PredictionPlayerBackup = {}; // Clear the copy so its destructor doesn't try delete the psprites list
// Restore the camera instead of using the backup's copy, because spynext/prev
// could cause it to change during prediction.

View file

@ -119,8 +119,6 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines)
PolyMaskedCycles.Reset();
PolyDrawerWaitCycles.Reset();
NetUpdate();
DontMapLines = dontmaplines;
R_SetupFrame(Viewpoint, Viewwindow, actor);
@ -169,8 +167,6 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines)
if (Viewpoint.camera)
Viewpoint.camera->renderflags = savedflags;
interpolator.RestoreInterpolations ();
NetUpdate();
}
void PolyRenderer::RenderRemainingPlayerSprites()

View file

@ -54,20 +54,10 @@ EXTERN_CVAR(String, language)
uint32_t LanguageIDs[4];
void I_Tactile(int /*on*/, int /*off*/, int /*total*/)
{
}
ticcmd_t* I_BaseTiccmd()
{
static ticcmd_t emptycmd;
return &emptycmd;
}
//
// SetLanguageIDs
//

View file

@ -71,7 +71,7 @@ public:
virtual void NetProgress(int count);
virtual void NetMessage(const char *format, ...);
virtual void NetDone();
virtual bool NetLoop(bool (*timerCallback)(void*), void* userData);
virtual bool NetLoop(std::function<bool()> callback);
};
@ -153,11 +153,11 @@ void FBasicStartupScreen::NetDone()
FConsoleWindow::GetInstance().NetDone();
}
bool FBasicStartupScreen::NetLoop(bool (*timerCallback)(void*), void* const userData)
bool FBasicStartupScreen::NetLoop(std::function<bool()> callback)
{
while (true)
{
if (timerCallback(userData))
if (callback())
{
break;
}

View file

@ -79,17 +79,6 @@ void I_StartFrame (void);
// Can call D_PostEvent.
void I_StartTic (void);
// Asynchronous interrupt functions should maintain private queues
// that are read by the synchronous functions
// to be converted into events.
// Either returns a null ticcmd,
// or calls a loadable driver to build it.
// This ticcmd will then be modified by the gameloop
// for normal input.
ticcmd_t *I_BaseTiccmd (void);
// Called by M_Responder when quit is selected.
// Clean exit, displays sell blurb.
void I_Quit (void);

View file

@ -75,12 +75,6 @@ void I_Tactile (int /*on*/, int /*off*/, int /*total*/)
{
}
ticcmd_t emptycmd;
ticcmd_t *I_BaseTiccmd(void)
{
return &emptycmd;
}
void I_BeginRead(void)
{
}

View file

@ -58,7 +58,7 @@ class FTTYStartupScreen : public FStartupScreen
void NetProgress(int count);
void NetMessage(const char *format, ...); // cover for printf
void NetDone();
bool NetLoop(bool (*timer_callback)(void *), void *userdata);
bool NetLoop(std::function<bool()> callback);
protected:
bool DidNetInit;
int NetMaxPos, NetCurPos;
@ -304,7 +304,7 @@ void FTTYStartupScreen::NetProgress(int count)
//
//===========================================================================
bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
bool FTTYStartupScreen::NetLoop(std::function<bool()> callback)
{
fd_set rfds;
struct timeval tv;
@ -328,7 +328,7 @@ bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
}
else if (retval == 0)
{
if (timer_callback (userdata))
if (callback())
{
fputc ('\n', stderr);
return true;

View file

@ -35,6 +35,8 @@
** Actual implementation is system-specific.
*/
#include <functional>
class FStartupScreen
{
public:
@ -51,7 +53,7 @@ public:
virtual void NetProgress(int count);
virtual void NetMessage(const char *format, ...); // cover for printf
virtual void NetDone();
virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata);
virtual bool NetLoop(std::function<bool()> callback);
protected:
int MaxPos, CurPos, NotchPos;
};

View file

@ -433,8 +433,8 @@ static bool CheatAddKey (cheatseq_t *cheat, uint8_t key, bool *eat)
static bool Cht_Generic (cheatseq_t *cheat)
{
Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (cheat->Args[0]);
network->WriteByte (DEM_GENERICCHEAT);
network->WriteByte (cheat->Args[0]);
return true;
}

View file

@ -584,7 +584,7 @@ CCMD(finishgame)
return;
}
// This CCMD simulates an end-of-game action and exists to end mods that never exit their last level.
Net_WriteByte(DEM_FINISHGAME);
network->WriteByte(DEM_FINISHGAME);
}
ADD_STAT(statistics)

View file

@ -85,9 +85,6 @@ namespace swrenderer
return;
}
if (Thread->MainThread)
NetUpdate();
frontsector = curline->frontsector;
backsector = curline->backsector;

View file

@ -373,9 +373,6 @@ namespace swrenderer
WallSampler sampler(Thread->Viewport.get(), y1, texturemid, swal[x], yrepeat, lwal[x] + xoffset, xmagnitude, rw_pic);
Draw1Column(x, y1, y2, sampler);
}
if (Thread->MainThread)
NetUpdate();
}
void RenderWallPart::ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal)

View file

@ -142,7 +142,5 @@ namespace swrenderer
renderer.Render(this, xscale, yscale, alpha, additive, masked, colormap, tex);
}
}
if (thread->MainThread)
NetUpdate();
}
}

View file

@ -455,14 +455,8 @@ namespace swrenderer
int prevuniq2 = CurrentPortalUniq;
CurrentPortalUniq = prevuniq;
if (Thread->MainThread)
NetUpdate();
Thread->TranslucentPass->Render(); // this is required since with portals there often will be cases when more than 80% of the view is inside a portal.
if (Thread->MainThread)
NetUpdate();
Thread->Clip3D->LeaveSkybox(); // pop 3D floor height map
CurrentPortalUniq = prevuniq2;

View file

@ -144,8 +144,6 @@ namespace swrenderer
CameraLight::Instance()->SetCamera(MainThread()->Viewport->viewpoint, MainThread()->Viewport->RenderTarget, actor);
MainThread()->Viewport->SetupFreelook();
NetUpdate();
this->dontmaplines = dontmaplines;
// [RH] Setup particles for this frame
@ -271,9 +269,6 @@ namespace swrenderer
thread->OpaquePass->RenderScene();
thread->Clip3D->ResetClip(); // reset clips (floor/ceiling)
if (thread->MainThread)
NetUpdate();
if (viewactive)
{
thread->PlaneList->Render();
@ -281,13 +276,7 @@ namespace swrenderer
thread->Portal->RenderPlanePortals();
thread->Portal->RenderLinePortals();
if (thread->MainThread)
NetUpdate();
thread->TranslucentPass->Render();
if (thread->MainThread)
NetUpdate();
}
DrawerThreads::Execute(thread->DrawQueue);

View file

@ -541,8 +541,5 @@ namespace swrenderer
drawerargs.DrawMaskedColumn(thread, x, iscale, pic, frac + xiscale / 2, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, RenderStyle, false);
frac += xiscale;
}
if (thread->MainThread)
NetUpdate();
}
}

View file

@ -371,8 +371,5 @@ namespace swrenderer
}
}
}
if (thread->MainThread)
NetUpdate();
}
}

View file

@ -142,7 +142,6 @@ int sys_ostype = 0;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static ticcmd_t emptycmd;
static bool HasExited;
static WadStuff *WadList;
@ -166,20 +165,6 @@ void I_Tactile(int on, int off, int total)
on = off = total = 0;
}
//==========================================================================
//
// I_BaseTiccmd
//
// Returns an empty ticcmd. I have no idea why this should be system-
// specific.
//
//==========================================================================
ticcmd_t *I_BaseTiccmd()
{
return &emptycmd;
}
//==========================================================================
//
// I_DetectOS

View file

@ -72,16 +72,6 @@ void I_StartFrame (void);
// Can call D_PostEvent.
void I_StartTic (void);
// Asynchronous interrupt functions should maintain private queues
// that are read by the synchronous functions
// to be converted into events.
// Either returns a null ticcmd,
// or calls a loadable driver to build it.
// This ticcmd will then be modified by the gameloop
// for normal input.
ticcmd_t *I_BaseTiccmd (void);
// Called by M_Responder when quit is selected.
// Clean exit, displays sell blurb.

View file

@ -121,7 +121,7 @@ public:
void NetProgress(int count);
void NetMessage(const char *format, ...); // cover for printf
void NetDone();
bool NetLoop(bool (*timer_callback)(void *), void *userdata);
bool NetLoop(std::function<bool()> callback);
protected:
LRESULT NetMarqueeMode;
int NetMaxPos, NetCurPos;
@ -528,7 +528,7 @@ void FBasicStartupScreen :: NetProgress(int count)
//
//==========================================================================
bool FBasicStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
bool FBasicStartupScreen::NetLoop(std::function<bool()> callback)
{
BOOL bRet;
MSG msg;
@ -549,7 +549,7 @@ bool FBasicStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata
{
if (msg.message == WM_TIMER && msg.hwnd == Window && msg.wParam == 1337)
{
if (timer_callback (userdata))
if (callback())
{
KillTimer (NetStartPane, 1);
return true;