- Packet code implementation (merge from private c/s repo), world updates are now synced through snapshots. See tag SVN_SyncPoint_Dec2018 on master of the other repo.

- "Scratch pad" sprites implementation, to avoid desyncs in sprite indexes, clients will insert temporary sprites which are cleared out when they receive the next snapshot from the server.
- Patches from Striker which fix player stomping frag counts, the accept button when hosting a game through the menu, and a "noffire" command line parameter.
- Patches from NY00123: t_data sync optimizations to improve some jittery behavior on the client side.

git-svn-id: https://svn.eduke32.com/eduke32@7242 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
seventyfive 2018-12-08 00:40:39 +00:00
parent 7bd5fa42ee
commit 87cf4495bf
14 changed files with 5200 additions and 1964 deletions

View file

@ -1240,6 +1240,7 @@ int32_t rayintersect(int32_t x1, int32_t y1, int32_t z1, int32_t vx, int32_t vy,
#if !defined NETCODE_DISABLE #if !defined NETCODE_DISABLE
void do_insertsprite_at_headofstat(int16_t spritenum, int16_t statnum); void do_insertsprite_at_headofstat(int16_t spritenum, int16_t statnum);
int32_t insertspritestat(int16_t statnum); int32_t insertspritestat(int16_t statnum);
void do_deletespritestat(int16_t deleteme);
void do_insertsprite_at_headofsect(int16_t spritenum, int16_t sectnum); void do_insertsprite_at_headofsect(int16_t spritenum, int16_t sectnum);
void do_deletespritesect(int16_t deleteme); void do_deletespritesect(int16_t deleteme);
#endif #endif

View file

@ -7262,7 +7262,7 @@ LISTFN_STATIC int32_t insertspritestat(int16_t statnum)
} }
// remove sprite 'deleteme' from its status list // remove sprite 'deleteme' from its status list
static void do_deletespritestat(int16_t deleteme) LISTFN_STATIC void do_deletespritestat(int16_t deleteme)
{ {
int32_t const sectnum = sprite[deleteme].statnum; int32_t const sectnum = sprite[deleteme].statnum;
int32_t const prev = prevspritestat[deleteme]; int32_t const prev = prevspritestat[deleteme];

View file

@ -422,6 +422,9 @@ int32_t A_MoveSpriteClipdist(int32_t spriteNum, vec3_t const * const change, uin
int const isEnemy = A_CheckEnemySprite(pSprite); int const isEnemy = A_CheckEnemySprite(pSprite);
vec2_t const oldPos = *(vec2_t *)pSprite; vec2_t const oldPos = *(vec2_t *)pSprite;
// check to make sure the netcode didn't leave a deleted sprite in the sprite lists.
Bassert(pSprite->sectnum < MAXSECTORS);
if (pSprite->statnum == STAT_MISC || (isEnemy && pSprite->xrepeat < 4)) if (pSprite->statnum == STAT_MISC || (isEnemy && pSprite->xrepeat < 4))
{ {
pSprite->x += change->x; pSprite->x += change->x;
@ -472,6 +475,9 @@ int32_t A_MoveSpriteClipdist(int32_t spriteNum, vec3_t const * const change, uin
clipmove((vec3_t *)pSprite, &newSectnum, change->x << 13, change->y << 13, clipDist, ZOFFSET6, ZOFFSET6, clipType); clipmove((vec3_t *)pSprite, &newSectnum, change->x << 13, change->y << 13, clipDist, ZOFFSET6, ZOFFSET6, clipType);
pSprite->z = oldZ; pSprite->z = oldZ;
// Testing: For some reason the assert below this was tripping for clients
EDUKE32_UNUSED int16_t dbg_ClipMoveSectnum = newSectnum;
if (isEnemy) if (isEnemy)
{ {
// Handle potential stayput condition (map-provided or hard-coded). // Handle potential stayput condition (map-provided or hard-coded).
@ -501,6 +507,8 @@ int32_t A_MoveSpriteClipdist(int32_t spriteNum, vec3_t const * const change, uin
pSprite->ang += 768; pSprite->ang += 768;
} }
EDUKE32_UNUSED int16_t dbg_newSectnum2 = newSectnum;
if (newSectnum == -1) if (newSectnum == -1)
{ {
newSectnum = pSprite->sectnum; newSectnum = pSprite->sectnum;
@ -619,19 +627,16 @@ void A_DeleteSprite(int spriteNum)
if (sprite[spriteNum].picnum == MUSICANDSFX && actor[spriteNum].t_data[0] == 1) if (sprite[spriteNum].picnum == MUSICANDSFX && actor[spriteNum].t_data[0] == 1)
S_StopEnvSound(sprite[spriteNum].lotag, spriteNum); S_StopEnvSound(sprite[spriteNum].lotag, spriteNum);
// NetAlloc #ifdef NETCODE_DISABLE
if (Net_IsRelevantSprite(spriteNum))
{
Net_DeleteSprite(spriteNum);
return;
}
deletesprite(spriteNum); deletesprite(spriteNum);
#else
Net_DeleteSprite(spriteNum);
#endif
} }
void A_AddToDeleteQueue(int spriteNum) void A_AddToDeleteQueue(int spriteNum)
{ {
if (g_deleteQueueSize == 0) if (g_netClient || (g_deleteQueueSize == 0)) // [75] Clients should not use SpriteDeletionQueue[] and just set the sprites invisible immediately in A_DeleteSprite
{ {
A_DeleteSprite(spriteNum); A_DeleteSprite(spriteNum);
return; return;

View file

@ -184,30 +184,167 @@ typedef struct
#endif #endif
} actor_t; } actor_t;
// this struct needs to match the beginning of actor_t above // note: fields in this struct DO NOT have to be in this order,
typedef struct // however if you add something to this struct, please make sure
// a field gets added to ActorFields[], otherwise the field
// won't get synced over the network!
//
// I don't think the ActorFields array needs to be in the same order,
// need to verify this...
typedef struct netactor_s
{ {
int32_t t_data[10]; // 40b sometimes used to hold offsets to con code // actor fields
//--------------------------------------------
int32_t
t_data_0,
t_data_1,
t_data_2,
t_data_3,
t_data_4,
t_data_5,
t_data_6,
t_data_7,
t_data_8,
t_data_9;
#ifdef LUNATIC #ifdef LUNATIC
struct move mv;
struct action ac; int32_t
uint16_t actiontics; hvel,
uint16_t movflags; vvel;
int32_t
startframe,
numframes;
int32_t
viewtype,
incval,
delay;
int32_t
actiontics;
#endif #endif
int32_t flags; // 4b int32_t
vec3_t bpos; // 12b flags;
int32_t floorz, ceilingz; // 8b
vec2_t lastv; // 8b
int16_t picnum, ang, extra, owner; // 8b
int16_t movflag, tempang, timetosleep; // 6b
int16_t stayput;
uint8_t cgg, lasttransport;
spritetype sprite; int32_t
int16_t netIndex; bpos_x,
bpos_y,
bpos_z;
int32_t
floorz,
ceilingz,
lastvx,
lastvy,
lasttransport,
picnum,
ang,
extra,
owner,
movflag,
tempang,
timetosleep,
stayput,
dispicnum;
#if defined LUNATIC
int32_t movflags;
#endif
// note: lightId, lightcount, lightmaxrange are not synchronized between client and server
int32_t
cgg;
// sprite fields
//-----------------------------
int32_t
spr_x,
spr_y,
spr_z,
spr_cstat,
spr_picnum,
spr_shade,
spr_pal,
spr_clipdist,
spr_blend,
spr_xrepeat,
spr_yrepeat,
spr_xoffset,
spr_yoffset,
spr_sectnum,
spr_statnum,
spr_ang,
spr_owner,
spr_xvel,
spr_yvel,
spr_zvel,
spr_lotag,
spr_hitag,
spr_extra;
//---------------------------------------------
//spriteext fields
int32_t
ext_mdanimtims,
ext_mdanimcur,
ext_angoff,
ext_pitch,
ext_roll,
ext_offset_x,
ext_offset_y,
ext_offset_z,
ext_flags,
ext_xpanning,
ext_ypanning;
float ext_alpha;
// DON'T send tsprites over the internet
//--------------------------------------------
//spritesmooth fields
float sm_smoothduration;
int32_t
sm_mdcurframe,
sm_mdoldframe,
sm_mdsmooth;
//--------------------------------------------
// SpriteProjectile fields
// may want to put projectile fields here
int32_t netIndex;
} netactor_t; } netactor_t;
#pragma pack(pop) #pragma pack(pop)

View file

@ -62,6 +62,7 @@ void G_ShowParameterHelp(void)
"-mh [file.def]\tInclude an additional definitions module\n" "-mh [file.def]\tInclude an additional definitions module\n"
"-mx [file.con]\tInclude an additional CON script module\n" "-mx [file.con]\tInclude an additional CON script module\n"
"-m\t\tDisable enemies\n" "-m\t\tDisable enemies\n"
"-noffire\t\tDisable friendly fire\n"
#ifndef EDUKE32_STANDALONE #ifndef EDUKE32_STANDALONE
"-nam\t\tRun in NAM compatibility mode\n" "-nam\t\tRun in NAM compatibility mode\n"
"-napalm\t\tRun in NAPALM compatibility mode\n" "-napalm\t\tRun in NAPALM compatibility mode\n"
@ -176,6 +177,7 @@ void G_CheckCommandLine(int32_t argc, char const * const * argv)
ud.m_respawn_inventory = 0; ud.m_respawn_inventory = 0;
ud.warp_on = 0; ud.warp_on = 0;
ud.cashman = 0; ud.cashman = 0;
ud.m_ffire = 1;
ud.m_player_skill = ud.player_skill = 2; ud.m_player_skill = ud.player_skill = 2;
g_player[0].wchoice[0] = 3; g_player[0].wchoice[0] = 3;
g_player[0].wchoice[1] = 4; g_player[0].wchoice[1] = 4;
@ -420,6 +422,12 @@ void G_CheckCommandLine(int32_t argc, char const * const * argv)
i++; i++;
continue; continue;
} }
if (!Bstrcasecmp(c+1, "noffire"))
{
ud.m_ffire = 0;
i++;
continue;
}
if (!Bstrcasecmp(c+1, "rts")) if (!Bstrcasecmp(c+1, "rts"))
{ {
if (argc > i+1) if (argc > i+1)

View file

@ -268,7 +268,6 @@ void CONFIG_SetDefaults(void)
ud.idplayers = 1; ud.idplayers = 1;
ud.levelstats = 0; ud.levelstats = 0;
ud.lockout = 0; ud.lockout = 0;
ud.m_ffire = 1;
ud.m_marker = 1; ud.m_marker = 1;
ud.maxautosaves = 5; ud.maxautosaves = 5;
ud.menu_scrollbartilenum = -1; ud.menu_scrollbartilenum = -1;

View file

@ -1268,7 +1268,16 @@ static int32_t G_InitActor(int32_t i, int32_t tilenum, int32_t set_movflag_uncon
int32_t A_InsertSprite(int16_t whatsect,int32_t s_x,int32_t s_y,int32_t s_z,int16_t s_pn,int8_t s_s, int32_t A_InsertSprite(int16_t whatsect,int32_t s_x,int32_t s_y,int32_t s_z,int16_t s_pn,int8_t s_s,
uint8_t s_xr,uint8_t s_yr,int16_t s_a,int16_t s_ve,int16_t s_zv,int16_t s_ow,int16_t s_ss) uint8_t s_xr,uint8_t s_yr,int16_t s_a,int16_t s_ve,int16_t s_zv,int16_t s_ow,int16_t s_ss)
{ {
int const newSprite = Net_IsRelevantStat(s_ss) ? Net_InsertSprite(whatsect, s_ss) : insertsprite(whatsect, s_ss);
int32_t newSprite;
#ifdef NETCODE_DISABLE
newSprite = insertsprite(whatsect, s_ss);
#else
newSprite = Net_InsertSprite(whatsect, s_ss);
#endif
if (EDUKE32_PREDICT_FALSE((unsigned)newSprite >= MAXSPRITES)) if (EDUKE32_PREDICT_FALSE((unsigned)newSprite >= MAXSPRITES))
{ {
@ -4727,9 +4736,9 @@ void G_HandleLocalKeys(void)
tempbuf[ridiculeNum++] = myconnectindex; tempbuf[ridiculeNum++] = myconnectindex;
if (g_netClient) if (g_netClient)
enet_peer_send(g_netClientPeer, CHAN_CHAT, enet_packet_create(tempbuf, ridiculeNum, 0)); enet_peer_send(g_netClientPeer, CHAN_CHAT, enet_packet_create(&tempbuf[0], ridiculeNum, 0));
else if (g_netServer) else if (g_netServer)
enet_host_broadcast(g_netServer, CHAN_CHAT, enet_packet_create(tempbuf, ridiculeNum, 0)); enet_host_broadcast(g_netServer, CHAN_CHAT, enet_packet_create(&tempbuf[0], ridiculeNum, 0));
#endif #endif
pus = NUMPAGES; pus = NUMPAGES;
pub = NUMPAGES; pub = NUMPAGES;
@ -4748,9 +4757,9 @@ void G_HandleLocalKeys(void)
tempbuf[2] = myconnectindex; tempbuf[2] = myconnectindex;
if (g_netClient) if (g_netClient)
enet_peer_send(g_netClientPeer, CHAN_CHAT, enet_packet_create(tempbuf, 3, 0)); enet_peer_send(g_netClientPeer, CHAN_CHAT, enet_packet_create(&tempbuf[0], 3, 0));
else if (g_netServer) else if (g_netServer)
enet_host_broadcast(g_netServer, CHAN_CHAT, enet_packet_create(tempbuf, 3, 0)); enet_host_broadcast(g_netServer, CHAN_CHAT, enet_packet_create(&tempbuf[0], 3, 0));
} }
#endif #endif
pus = NUMPAGES; pus = NUMPAGES;
@ -6599,6 +6608,14 @@ MAIN_LOOP_RESTART:
Menu_Change(MENU_MAIN); Menu_Change(MENU_MAIN);
if(g_netClient)
{
OSD_Printf("Waiting for initial snapshot...");
Net_WaitForInitialSnapshot();
}
if (g_networkMode != NET_DEDICATED_SERVER) if (g_networkMode != NET_DEDICATED_SERVER)
{ {
G_GetCrosshairColor(); G_GetCrosshairColor();
@ -6662,6 +6679,11 @@ MAIN_LOOP_RESTART:
ud.warp_on = 0; ud.warp_on = 0;
KB_KeyDown[sc_Pause] = 0; // JBF: I hate the pause key KB_KeyDown[sc_Pause] = 0; // JBF: I hate the pause key
if(g_netClient)
{
ready2send = 1; // TESTING
}
do //main loop do //main loop
{ {
if (handleevents() && quitevent) if (handleevents() && quitevent)
@ -6981,10 +7003,17 @@ int G_DoMoveThings(void)
G_AnimateWalls(); G_AnimateWalls();
A_MoveCyclers(); A_MoveCyclers();
if (g_netServer && (everyothertime % 10) == 0) if ((everyothertime % 10) == 0)
{
if(g_netServer)
{ {
Net_SendMapUpdate(); Net_SendMapUpdate();
} }
else if(g_netClient)
{
Net_StoreClientState();
}
}
} }
if (g_netClient) //Slave if (g_netClient) //Slave

View file

@ -1319,7 +1319,7 @@ static MenuOption_t MEO_NETOPTIONS_MAPEXITS = MAKE_MENUOPTION( &MF_Bluefont, &ME
static MenuEntry_t ME_NETOPTIONS_MAPEXITS = MAKE_MENUENTRY( "Map Exits", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_MAPEXITS, Option ); static MenuEntry_t ME_NETOPTIONS_MAPEXITS = MAKE_MENUENTRY( "Map Exits", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_MAPEXITS, Option );
static MenuOption_t MEO_NETOPTIONS_FRFIRE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OffOn, &ud.m_ffire ); static MenuOption_t MEO_NETOPTIONS_FRFIRE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OffOn, &ud.m_ffire );
static MenuEntry_t ME_NETOPTIONS_FRFIRE = MAKE_MENUENTRY( "Fr. Fire", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_FRFIRE, Option ); static MenuEntry_t ME_NETOPTIONS_FRFIRE = MAKE_MENUENTRY( "Fr. Fire", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_FRFIRE, Option );
static MenuEntry_t ME_NETOPTIONS_ACCEPT = MAKE_MENUENTRY( "Accept", &MF_Redfont, &MEF_NetSetup_Confirm, &MEO_NULL, Link ); static MenuEntry_t ME_NETOPTIONS_ACCEPT = MAKE_MENUENTRY( "Accept", &MF_Redfont, &MEF_NetSetup_Confirm, &MEO_NETWORK_HOSTGAME, Link );
static MenuEntry_t *MEL_NETOPTIONS[] = { static MenuEntry_t *MEL_NETOPTIONS[] = {
&ME_NETOPTIONS_GAMETYPE, &ME_NETOPTIONS_GAMETYPE,

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/* /*
Copyright (C) 2010 EDuke32 developers and contributors Copyright (C) 2017 EDuke32 developers and contributors
This file is part of EDuke32. This file is part of EDuke32.
@ -23,10 +23,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef netplay_h_ #ifndef netplay_h_
#define netplay_h_ #define netplay_h_
#ifdef _WIN32 // As of Nov. of 2018, the version of gcc that the Makefile is using is too old for [[maybe_unused]],
// include this before enet does // but __attribute__ is GNU C only.
# define NEED_WINSOCK2_H #ifdef __GNUC__
# include "windows_inc.h" #define EDUKE32_UNUSED __attribute__((unused))
#else
#define EDUKE32_UNUSED
#endif #endif
#include "enet/enet.h" #include "enet/enet.h"
@ -41,16 +43,8 @@ extern char g_netPassword[32];
extern int32_t g_netDisconnect; extern int32_t g_netDisconnect;
extern int32_t g_netPlayersWaiting; extern int32_t g_netPlayersWaiting;
extern enet_uint16 g_netPort; extern enet_uint16 g_netPort;
#ifndef NETCODE_DISABLE
extern int32_t g_networkMode; extern int32_t g_networkMode;
#else
#define g_networkMode 0
#endif
extern int32_t g_netIndex; extern int32_t g_netIndex;
extern int32_t lastsectupdate[MAXSECTORS];
extern int32_t lastupdate[MAXSPRITES];
extern int32_t lastwallupdate[MAXWALLS];
extern int16_t g_netStatnums[];
#define NET_REVISIONS 64 #define NET_REVISIONS 64
@ -63,6 +57,7 @@ enum netchan_t
CHAN_MAX CHAN_MAX
}; };
enum DukePacket_t enum DukePacket_t
{ {
PACKET_MASTER_TO_SLAVE, PACKET_MASTER_TO_SLAVE,
@ -77,7 +72,7 @@ enum DukePacket_t
PACKET_AUTH, PACKET_AUTH,
PACKET_PLAYER_PING, PACKET_PLAYER_PING,
PACKET_PLAYER_READY, PACKET_PLAYER_READY,
PACKET_MAP_STREAM, PACKET_WORLD_UPDATE, //[75]
// any packet with an ID higher than PACKET_BROADCAST is rebroadcast by server // any packet with an ID higher than PACKET_BROADCAST is rebroadcast by server
// so hacked clients can't create fake server packets and get the server to // so hacked clients can't create fake server packets and get the server to
@ -86,7 +81,7 @@ enum DukePacket_t
// channel the packet was broadcast on // channel the packet was broadcast on
PACKET_BROADCAST, PACKET_BROADCAST,
PACKET_NEW_GAME, PACKET_NEW_GAME, // [S->C]
PACKET_RTS, PACKET_RTS,
PACKET_CLIENT_INFO, PACKET_CLIENT_INFO,
PACKET_MESSAGE, PACKET_MESSAGE,
@ -97,6 +92,8 @@ enum DukePacket_t
PACKET_MAP_VOTE_CANCEL, PACKET_MAP_VOTE_CANCEL,
}; };
enum netdisconnect_t enum netdisconnect_t
{ {
DISC_BAD_PASSWORD = 1, DISC_BAD_PASSWORD = 1,
@ -116,41 +113,101 @@ enum netmode_t
NET_DEDICATED_SERVER NET_DEDICATED_SERVER
}; };
#define NETMAXACTORS 1024
//[75]
typedef struct netWall_s
{
uint16_t netIndex;
int32_t x,
y,
point2,
nextwall,
nextsector,
cstat,
picnum,
overpicnum,
shade,
pal,
xrepeat,
yrepeat,
xpanning,
ypanning,
lotag,
hitag,
extra;
} netWall_t;
// sector struct with all 32 bit entries
typedef struct netSector_s
{
uint16_t netIndex;
int32_t wallptr,
wallnum,
ceilingz,
floorz,
ceilingstat,
floorstat,
ceilingpicnum,
ceilingheinum,
ceilingshade,
ceilingpal,
ceilingxpanning,
ceilingypanning,
floorpicnum,
floorheinum,
floorshade,
floorpal,
floorxpanning,
floorypanning,
visibility,
fogpal,
lotag,
hitag,
extra;
} netSector_t;
const uint64_t cSnapshotMemUsage = NET_REVISIONS * (
(sizeof(netWall_t) * MAXWALLS)
+ (sizeof(netSector_t) * MAXSECTORS)
+ (sizeof(netactor_t) * MAXSPRITES)
);
#pragma pack(push,1) #pragma pack(push,1)
typedef struct typedef struct netmapstate_s
{ {
uint32_t revisionNumber;
uint32_t numActors; int32_t maxActorIndex;
netactor_t actor[NETMAXACTORS]; netactor_t actor[MAXSPRITES];
netWall_t wall[MAXWALLS];
netSector_t sector[MAXSECTORS];
} netmapstate_t; } netmapstate_t;
typedef struct
{
uint32_t numActors;
uint32_t numToDelete;
uint32_t fromRevision;
uint32_t toRevision;
char data[MAXSPRITES *sizeof(netactor_t)];
} netmapdiff_t;
extern netmapstate_t *g_multiMapState[MAXPLAYERS];
extern netmapstate_t *g_multiMapRevisions[NET_REVISIONS];
#pragma pack(pop) #pragma pack(pop)
#pragma pack(push,1) #pragma pack(push,1)
typedef struct typedef struct playerupdate_s
{ {
vec3_t pos; vec3_t pos;
vec3_t opos; vec3_t opos;
vec3_t vel; vec3_t vel;
int16_t ang;
int16_t horiz; fix16_t q16ang;
int16_t horizoff; fix16_t q16horiz;
fix16_t q16horizoff;
int16_t ping; int16_t ping;
int16_t playerindex; int16_t playerindex;
int16_t deadflag; int16_t deadflag;
@ -159,7 +216,7 @@ typedef struct
#pragma pack(pop) #pragma pack(pop)
#pragma pack(push,1) #pragma pack(push,1)
typedef struct typedef struct newgame_s
{ {
int8_t header; int8_t header;
int8_t connection; int8_t connection;
@ -177,182 +234,120 @@ typedef struct
} newgame_t; } newgame_t;
#pragma pack(pop) #pragma pack(pop)
extern newgame_t pendingnewgame; extern newgame_t pendingnewgame;
#ifndef NETCODE_DISABLE #ifndef NETCODE_DISABLE
// Connect/Disconnect // Connect/Disconnect
void Net_Connect(const char *srvaddr); void Net_Connect(const char *srvaddr);
void Net_Disconnect(void);
void Net_ReceiveDisconnect(ENetEvent *event);
// Packet Handlers // Packet Handlers
#endif #endif
void Net_GetPackets(void); void Net_GetPackets(void);
#ifndef NETCODE_DISABLE #ifndef NETCODE_DISABLE
void Net_HandleServerPackets(void);
void Net_HandleClientPackets(void);
void Net_ParseClientPacket(ENetEvent *event);
void Net_ParseServerPacket(ENetEvent *event);
void Net_ParsePacketCommon(uint8_t *pbuf, int32_t packbufleng, int32_t serverpacketp);
void Net_SendAcknowledge(ENetPeer *client);
void Net_ReceiveAcknowledge(uint8_t *pbuf, int32_t packbufleng);
void Net_SendChallenge();
void Net_ReceiveChallenge(uint8_t *pbuf, int32_t packbufleng, ENetEvent *event);
void Net_SendNewPlayer(int32_t newplayerindex);
void Net_ReceiveNewPlayer(uint8_t *pbuf, int32_t packbufleng);
void Net_SendPlayerIndex(int32_t index, ENetPeer *peer);
void Net_ReceivePlayerIndex(uint8_t *pbuf, int32_t packbufleng);
void Net_SendClientInfo(void); void Net_SendClientInfo(void);
void Net_ReceiveClientInfo(uint8_t *pbuf, int32_t packbufleng, int32_t fromserver);
void Net_SendUserMapName(void); void Net_SendUserMapName(void);
void Net_ReceiveUserMapName(uint8_t *pbuf, int32_t packbufleng);
netmapstate_t *Net_GetRevision(uint8_t revision, uint8_t cancreate);
void Net_SendMapUpdate(void); void Net_SendMapUpdate(void);
void Net_ReceiveMapUpdate(ENetEvent *event);
void Net_FillMapDiff(uint32_t fromRevision, uint32_t toRevision);
void Net_SaveMapState(netmapstate_t *save);
void Net_RestoreMapState();
void Net_CopyToNet(int32_t i, netactor_t *netactor);
void Net_CopyFromNet(int32_t i, netactor_t *netactor);
int32_t Net_ActorsAreDifferent(netactor_t *actor1, netactor_t *actor2);
int32_t Net_IsRelevantSprite(int32_t i);
int32_t Net_IsRelevantStat(int32_t stat);
int32_t Net_InsertSprite(int32_t sect, int32_t stat); int32_t Net_InsertSprite(int32_t sect, int32_t stat);
void Net_DeleteSprite(int32_t spritenum); void Net_DeleteSprite(int32_t spritenum);
void Net_FillPlayerUpdate(playerupdate_t *update, int32_t player);
void Net_ExtractPlayerUpdate(playerupdate_t *update, int32_t type);
void Net_SendServerUpdates(void); void Net_SendServerUpdates(void);
void Net_ReceiveServerUpdate(ENetEvent *event);
void Net_SendClientUpdate(void); void Net_SendClientUpdate(void);
void Net_ReceiveClientUpdate(ENetEvent *event);
void Net_SendMessage(void); void Net_SendMessage(void);
void Net_ReceiveMessage(uint8_t *pbuf, int32_t packbufleng);
void Net_StartNewGame(); void Net_StartNewGame();
void Net_NotifyNewGame(); void Net_NotifyNewGame();
void Net_SendNewGame(int32_t frommenu, ENetPeer *peer); void Net_SendNewGame(int32_t frommenu, ENetPeer *peer);
void Net_ReceiveNewGame(ENetEvent *event);
void Net_FillNewGame(newgame_t *newgame, int32_t frommenu); void Net_FillNewGame(newgame_t *newgame, int32_t frommenu);
void Net_ExtractNewGame(newgame_t *newgame, int32_t menuonly);
void Net_SendMapVoteInitiate(void); void Net_SendMapVoteInitiate(void);
void Net_ReceiveMapVoteInitiate(uint8_t *pbuf);
void Net_SendMapVote(int32_t votefor); void Net_SendMapVote(int32_t votefor);
void Net_ReceiveMapVote(uint8_t *pbuf);
void Net_CheckForEnoughVotes();
void Net_SendMapVoteCancel(int32_t failed); void Net_SendMapVoteCancel(int32_t failed);
void Net_ReceiveMapVoteCancel(uint8_t *pbuf);
void Net_StoreClientState(void);
////////// //////////
void Net_ResetPrediction(void); void Net_ResetPrediction(void);
void Net_SpawnPlayer(int32_t player); void Net_SpawnPlayer(int32_t player);
void Net_SyncPlayer(ENetEvent *event);
void Net_WaitForServer(void); void Net_WaitForServer(void);
void faketimerhandler(void); void faketimerhandler(void);
void Net_InitMapStateHistory();
void Net_AddWorldToInitialSnapshot();
// Debugging
int32_t Dbg_PacketSent(enum DukePacket_t iPacketType);
void DumpMapStateHistory();
void Net_WaitForInitialSnapshot();
#else #else
/* NETCODE_ENABLE is not defined */ // note: don't include faketimerhandler in this
#define Net_GetPackets(...) ((void)0)
// Connect/Disconnect
#define Net_Connect(...) ((void)0) #define Net_Connect(...) ((void)0)
#define Net_Disconnect(...) ((void)0)
#define Net_ReceiveDisconnect(...) ((void)0)
// Packet Handlers
#define Net_HandleServerPackets(...) ((void)0)
#define Net_HandleClientPackets(...) ((void)0)
#define Net_ParseClientPacket(...) ((void)0)
#define Net_ParseServerPacket(...) ((void)0)
#define Net_ParsePacketCommon(...) ((void)0)
#define Net_SendAcknowledge(...) ((void)0)
#define Net_ReceiveAcknowledge(...) ((void)0)
#define Net_SendChallenge(...) ((void)0)
#define Net_ReceiveChallenge(...) ((void)0)
#define Net_SendNewPlayer(...) ((void)0)
#define Net_ReceiveNewPlayer(...) ((void)0)
#define Net_SendPlayerIndex(...) ((void)0)
#define Net_ReceivePlayerIndex(...) ((void)0)
#define Net_SendClientInfo(...) ((void)0) #define Net_SendClientInfo(...) ((void)0)
#define Net_ReceiveClientInfo(...) ((void)0)
#define Net_SendUserMapName(...) ((void)0) #define Net_SendUserMapName(...) ((void)0)
#define Net_ReceiveUserMapName(...) ((void)0)
#define Net_SendClientSync(...) ((void)0) #define Net_SendClientSync(...) ((void)0)
#define Net_ReceiveClientSync(...) ((void)0) #define Net_ReceiveClientSync(...) ((void)0)
#define Net_SendMapUpdate(...) ((void)0) #define Net_SendMapUpdates(...) ((void)0)
#define Net_ReceiveMapUpdate(...) ((void)0) #define Net_ReceiveMapUpdate(...) ((void)0)
#define Net_FillPlayerUpdate(...) ((void)0)
#define Net_ExtractPlayerUpdate(...) ((void)0)
#define Net_SendServerUpdates(...) ((void)0) #define Net_SendServerUpdates(...) ((void)0)
#define Net_ReceiveServerUpdate(...) ((void)0)
#define Net_SendClientUpdate(...) ((void)0) #define Net_SendClientUpdate(...) ((void)0)
#define Net_ReceiveClientUpdate(...) ((void)0)
#define Net_SendMessage(...) ((void)0) #define Net_SendMessage(...) ((void)0)
#define Net_ReceiveMessage(...) ((void)0)
#define Net_StartNewGame(...) ((void)0) #define Net_StartNewGame(...) ((void)0)
#define Net_SendNewGame(...) ((void)0) #define Net_SendNewGame(...) ((void)0)
#define Net_ReceiveNewGame(...) ((void)0)
#define Net_FillNewGame(...) ((void)0) #define Net_FillNewGame(...) ((void)0)
#define Net_ExtractNewGame(...) ((void)0)
#define Net_SendMapVoteInitiate(...) ((void)0) #define Net_SendMapVoteInitiate(...) ((void)0)
#define Net_ReceiveMapVoteInitiate(...) ((void)0)
#define Net_SendMapVote(...) ((void)0) #define Net_SendMapVote(...) ((void)0)
#define Net_ReceiveMapVote(...) ((void)0)
#define Net_CheckForEnoughVotes(...) ((void)0)
#define Net_SendMapVoteCancel(...) ((void)0) #define Net_SendMapVoteCancel(...) ((void)0)
#define Net_ReceiveMapVoteCancel(...) ((void)0)
//////////
#define Net_ResetPrediction(...) ((void)0) #define Net_ResetPrediction(...) ((void)0)
#define Net_RestoreMapState(...) ((void)0) #define Net_RestoreMapState(...) ((void)0)
#define Net_SyncPlayer(...) ((void)0)
#define Net_WaitForServer(...) ((void)0) #define Net_WaitForServer(...) ((void)0)
#define Net_ActorsAreDifferent(...) 0 #define Net_InsertSprite(...) ((void)0)
#define Net_IsRelevantSprite(...) 0
#define Net_IsRelevantStat(...) 0
#define Net_InsertSprite(...) 0
#define Net_DeleteSprite(...) ((void)0) #define Net_DeleteSprite(...) ((void)0)
#define Net_NotifyNewGame(...) ((void)0) #define Net_NotifyNewGame(...) ((void)0)
#define Net_WaitForInitialSnapshot(...) ((void)0)
#define Net_SendMapUpdate(...) ((void)0)
#define Net_StoreClientState(...) ((void)0)
#define Net_InitMapStateHistory(...) ((void)0)
#define Net_AddWorldToInitialSnapshot(...) ((void)0)
#define DumpMapStateHistory(...) ((void)0)
#endif #endif
#endif // netplay_h_ #endif // netplay_h_

View file

@ -1502,6 +1502,36 @@ static int osdcmd_cvar_set_multi(osdcmdptr_t parm)
return r; return r;
} }
#ifndef NETCODE_DISABLE
static int32_t osdcmd_dumpmapstate(osdfuncparm_t const * const)
{
// this command takes no parameters
DumpMapStateHistory();
return OSDCMD_OK;
}
static int32_t osdcmd_playerinfo(osdfuncparm_t const * const)
{
OSD_Printf("Your player index is %d.\n", myconnectindex);
for(int32_t playerIndex = 0; playerIndex < MAXPLAYERS; playerIndex++)
{
if(g_player[playerIndex].ps == nullptr)
{
OSD_Printf("g_player[%d]: ps unallocated.\n", playerIndex);
}
else
{
OSD_Printf("g_player[%d]: ps->i is %d.\n", playerIndex, g_player[playerIndex].ps->i);
}
}
return OSDCMD_OK;
}
#endif
int32_t registerosdcommands(void) int32_t registerosdcommands(void)
{ {
static osdcvardata_t cvars_game[] = static osdcvardata_t cvars_game[] =
@ -1745,6 +1775,12 @@ int32_t registerosdcommands(void)
#ifdef USE_OPENGL #ifdef USE_OPENGL
baselayer_osdcmd_vidmode_func = osdcmd_vidmode; baselayer_osdcmd_vidmode_func = osdcmd_vidmode;
#endif #endif
#ifndef NETCODE_DISABLE
OSD_RegisterFunction("dumpmapstates", "Dumps current snapshots to CL/Srv_MapStates.bin", osdcmd_dumpmapstate);
OSD_RegisterFunction("playerinfo", "Prints information about the current player", osdcmd_playerinfo);
#endif
return 0; return 0;
} }

View file

@ -3674,6 +3674,7 @@ void P_FragPlayer(int playerNum)
#ifndef NETCODE_DISABLE #ifndef NETCODE_DISABLE
if (g_netServer) if (g_netServer)
{ {
// this packet might not be needed anymore with the new snapshot code
packbuf[0] = PACKET_FRAG; packbuf[0] = PACKET_FRAG;
packbuf[1] = playerNum; packbuf[1] = playerNum;
packbuf[2] = pPlayer->frag_ps; packbuf[2] = pPlayer->frag_ps;
@ -3681,7 +3682,7 @@ void P_FragPlayer(int playerNum)
B_BUF32(&packbuf[4], ticrandomseed); B_BUF32(&packbuf[4], ticrandomseed);
packbuf[8] = myconnectindex; packbuf[8] = myconnectindex;
enet_host_broadcast(g_netServer, CHAN_GAMESTATE, enet_packet_create(packbuf, 9, ENET_PACKET_FLAG_RELIABLE)); enet_host_broadcast(g_netServer, CHAN_GAMESTATE, enet_packet_create(&packbuf[0], 9, ENET_PACKET_FLAG_RELIABLE));
} }
#endif #endif
} }
@ -5473,9 +5474,9 @@ HORIZONLY:;
break; break;
case APLAYER__STATIC: case APLAYER__STATIC:
{ {
int playerNum = P_Get(pPlayer->actorsqu); const int playerSquished = P_Get(pPlayer->actorsqu);
P_QuickKill(g_player[playerNum].ps); P_QuickKill(g_player[playerSquished].ps);
g_player[playerNum].ps->frag_ps = playerNum; g_player[playerSquished].ps->frag_ps = playerNum;
break; break;
} }
default: default:

View file

@ -223,7 +223,9 @@ typedef struct {
// NOTE: wchoice[HANDREMOTE_WEAPON .. MAX_WEAPONS-1] unused // NOTE: wchoice[HANDREMOTE_WEAPON .. MAX_WEAPONS-1] unused
uint8_t frags[MAXPLAYERS], wchoice[MAX_WEAPONS]; uint8_t frags[MAXPLAYERS], wchoice[MAX_WEAPONS];
char vote, gotvote, pingcnt, playerquitflag, ready;
char vote, gotvote, pingcnt, playerquitflag,
ready; // currently unused. May be used later to indicate that a player has pressed use on intermission to indicate they are ready to go on to the next map
char user_name[32]; char user_name[32];
uint32_t revision; uint32_t revision;
} playerdata_t; } playerdata_t;

View file

@ -35,7 +35,9 @@ static uint8_t precachehightile[2][MAXTILES>>3];
static int32_t g_precacheCount; static int32_t g_precacheCount;
static inline void flag_precache(int tile, int type) static int32_t NET_75_CHECK = 0;
static void flag_precache(int32_t tile, int32_t type)
{ {
if (!(gotpic[tile>>3] & pow2char[tile&7])) if (!(gotpic[tile>>3] & pow2char[tile&7]))
g_precacheCount++; g_precacheCount++;
@ -1906,8 +1908,10 @@ int G_EnterLevel(int gameMode)
int16_t playerAngle; int16_t playerAngle;
char levelName[BMAX_PATH]; char levelName[BMAX_PATH];
NET_75_CHECK++; // a major problem with how STAT_NETALLOC works, is that loadboard loads sprites directly into the arrays and does not take from
// STAT_NETALLOC, even though the loaded sprites are very, very likely to be relevant to the netcode.
if (!VOLUMEONE && Menu_HaveUserMap()) if (!VOLUMEONE && G_HaveUserMap())
{ {
if (engineLoadBoard(boardfilename, 0, &p0.pos, &playerAngle, &p0.cursectnum) < 0) if (engineLoadBoard(boardfilename, 0, &p0.pos, &playerAngle, &p0.cursectnum) < 0)
{ {
@ -1934,6 +1938,12 @@ int G_EnterLevel(int gameMode)
Bmemset(gotpic, 0, sizeof(gotpic)); Bmemset(gotpic, 0, sizeof(gotpic));
Bmemset(precachehightile, 0, sizeof(precachehightile)); Bmemset(precachehightile, 0, sizeof(precachehightile));
NET_75_CHECK++; // resetpspritevars attempts to insert player 0's sprite, which isn't going to work because we don't have
// the STAT_NETALLOC sprites allocated yet.
Net_NotifyNewGame();
prelevel(gameMode); prelevel(gameMode);
G_AlignWarpElevators(); G_AlignWarpElevators();
@ -1978,7 +1988,7 @@ int G_EnterLevel(int gameMode)
P_DoQuote(QUOTE_F1HELP,g_player[myconnectindex].ps); P_DoQuote(QUOTE_F1HELP,g_player[myconnectindex].ps);
#endif #endif
Net_NotifyNewGame(); //Net_NotifyNewGame();
Net_ResetPrediction(); Net_ResetPrediction();
//g_player[myconnectindex].ps->palette = palette; //g_player[myconnectindex].ps->palette = palette;
@ -2018,6 +2028,12 @@ int G_EnterLevel(int gameMode)
G_DrawBackground(); G_DrawBackground();
G_DrawRooms(myconnectindex,65536); G_DrawRooms(myconnectindex,65536);
if (g_netClient || g_netServer) // [75] : Initialize map states after map load
{
Net_InitMapStateHistory();
Net_AddWorldToInitialSnapshot();
}
Net_WaitForServer(); Net_WaitForServer();
return 0; return 0;
} }