Merge remote-tracking branch 'origin/next' into lift-savebuffer-limits

This commit is contained in:
Hanicef 2024-09-07 12:57:58 +02:00
commit f34476bf0a
14 changed files with 161 additions and 146 deletions

View file

@ -2622,6 +2622,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
boolean spectator; boolean spectator;
boolean outofcoop; boolean outofcoop;
boolean removing; boolean removing;
boolean muted;
INT16 bot; INT16 bot;
SINT8 pity; SINT8 pity;
INT16 rings; INT16 rings;
@ -2639,6 +2640,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
spectator = players[player].spectator; spectator = players[player].spectator;
outofcoop = players[player].outofcoop; outofcoop = players[player].outofcoop;
removing = players[player].removing; removing = players[player].removing;
muted = players[player].muted;
pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER)); pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER));
playerangleturn = players[player].angleturn; playerangleturn = players[player].angleturn;
oldrelangleturn = players[player].oldrelangleturn; oldrelangleturn = players[player].oldrelangleturn;
@ -2716,6 +2718,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->spectator = spectator; p->spectator = spectator;
p->outofcoop = outofcoop; p->outofcoop = outofcoop;
p->removing = removing; p->removing = removing;
p->muted = muted;
p->angleturn = playerangleturn; p->angleturn = playerangleturn;
p->oldrelangleturn = oldrelangleturn; p->oldrelangleturn = oldrelangleturn;

View file

@ -587,8 +587,8 @@ static void Command_CSay_f(void)
DoSayCommand(0, 1, HU_CSAY); DoSayCommand(0, 1, HU_CSAY);
} }
static tic_t spam_tokens[MAXPLAYERS] = { 1 }; // fill the buffer with 1 so the motd can be sent. UINT8 spam_tokens[MAXPLAYERS] = { 1 }; // fill the buffer with 1 so the motd can be sent.
static tic_t spam_tics[MAXPLAYERS]; tic_t spam_tics[MAXPLAYERS];
/** Receives a message, processing an ::XD_SAY command. /** Receives a message, processing an ::XD_SAY command.
* \sa DoSayCommand * \sa DoSayCommand
@ -649,14 +649,12 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
else else
spam_tokens[playernum] -= 1; spam_tokens[playernum] -= 1;
// run the lua hook even if we were supposed to eat the msg, netgame consistency goes first. if (spam_eatmsg)
return; // don't proceed if we were supposed to eat the message.
if (LUA_HookPlayerMsg(playernum, target, flags, msg)) if (LUA_HookPlayerMsg(playernum, target, flags, msg))
return; return;
if (spam_eatmsg)
return; // don't proceed if we were supposed to eat the message.
// If it's a CSAY, just CECHO and be done with it. // If it's a CSAY, just CECHO and be done with it.
if (flags & HU_CSAY) if (flags & HU_CSAY)
{ {

View file

@ -79,6 +79,9 @@ void HU_AddChatText(const char *text, boolean playsound);
// set true when entering a chat message // set true when entering a chat message
extern boolean chat_on; extern boolean chat_on;
extern UINT8 spam_tokens[MAXPLAYERS];
extern tic_t spam_tics[MAXPLAYERS];
extern patch_t *emeraldpics[3][8]; extern patch_t *emeraldpics[3][8];
extern patch_t *rflagico; extern patch_t *rflagico;
extern patch_t *bflagico; extern patch_t *bflagico;

View file

@ -1414,6 +1414,83 @@ static void IdleUpdate(void)
} }
} }
static void DedicatedIdleUpdate(INT32 *realtics)
{
const tic_t dedicatedidletime = cv_dedicatedidletime.value * TICRATE;
static tic_t dedicatedidletimeprev = 0;
static tic_t dedicatedidle = 0;
if (!server || !dedicated || gamestate != GS_LEVEL)
return;
if (dedicatedidletime > 0)
{
INT32 i;
boolean empty = true;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
{
empty = false;
break;
}
if (empty)
{
if (leveltime == 2)
{
// On next tick...
dedicatedidle = dedicatedidletime - 1;
}
else if (dedicatedidle >= dedicatedidletime)
{
if (D_GetExistingTextcmd(gametic, 0) || D_GetExistingTextcmd(gametic + 1, 0))
{
CONS_Printf("DEDICATED: Awakening from idle (Netxcmd detected...)\n");
dedicatedidle = 0;
}
else
{
(*realtics) = 0;
}
}
else
{
dedicatedidle += (*realtics);
if (dedicatedidle >= dedicatedidletime)
{
const char *idlereason = "at round start";
if (leveltime > 3)
idlereason = va("for %d seconds", dedicatedidle / TICRATE);
CONS_Printf("DEDICATED: No players %s, idling...\n", idlereason);
(*realtics) = 0;
dedicatedidle = dedicatedidletime;
}
}
}
else
{
if (dedicatedidle >= dedicatedidletime)
{
CONS_Printf("DEDICATED: Awakening from idle (Player detected...)\n");
}
dedicatedidle = 0;
}
}
else
{
if (dedicatedidletimeprev > 0 && dedicatedidle >= dedicatedidletimeprev)
{
CONS_Printf("DEDICATED: Awakening from idle (Idle disabled...)\n");
}
dedicatedidle = 0;
}
dedicatedidletimeprev = dedicatedidletime;
}
// Handle timeouts to prevent definitive freezes from happenning // Handle timeouts to prevent definitive freezes from happenning
static void HandleNodeTimeouts(void) static void HandleNodeTimeouts(void)
{ {
@ -1490,69 +1567,7 @@ void NetUpdate(void)
realtics = 5; realtics = 5;
} }
if (server && dedicated && gamestate == GS_LEVEL) DedicatedIdleUpdate(&realtics);
{
const tic_t dedicatedidletime = cv_dedicatedidletime.value * TICRATE;
static tic_t dedicatedidletimeprev = 0;
static tic_t dedicatedidle = 0;
if (dedicatedidletime > 0)
{
INT32 i;
for (i = 1; i < MAXNETNODES; ++i)
if (netnodes[i].ingame)
{
if (dedicatedidle >= dedicatedidletime)
{
CONS_Printf("DEDICATED: Awakening from idle (Node %d detected...)\n", i);
dedicatedidle = 0;
}
break;
}
if (i == MAXNETNODES)
{
if (leveltime == 2)
{
// On next tick...
dedicatedidle = dedicatedidletime-1;
}
else if (dedicatedidle >= dedicatedidletime)
{
if (D_GetExistingTextcmd(gametic, 0) || D_GetExistingTextcmd(gametic+1, 0))
{
CONS_Printf("DEDICATED: Awakening from idle (Netxcmd detected...)\n");
dedicatedidle = 0;
}
else
{
realtics = 0;
}
}
else if ((dedicatedidle += realtics) >= dedicatedidletime)
{
const char *idlereason = "at round start";
if (leveltime > 3)
idlereason = va("for %d seconds", dedicatedidle/TICRATE);
CONS_Printf("DEDICATED: No nodes %s, idling...\n", idlereason);
realtics = 0;
dedicatedidle = dedicatedidletime;
}
}
}
else
{
if (dedicatedidletimeprev > 0 && dedicatedidle >= dedicatedidletimeprev)
{
CONS_Printf("DEDICATED: Awakening from idle (Idle disabled...)\n");
}
dedicatedidle = 0;
}
dedicatedidletimeprev = dedicatedidletime;
}
gametime = nowtime; gametime = nowtime;

View file

@ -62,9 +62,6 @@ static doomdata_t reboundstore[MAXREBOUND];
static INT16 reboundsize[MAXREBOUND]; static INT16 reboundsize[MAXREBOUND];
static INT32 rebound_head, rebound_tail; static INT32 rebound_head, rebound_tail;
/// \brief bandwith of netgame
INT32 net_bandwidth;
/// \brief max length per packet /// \brief max length per packet
INT16 hardware_MAXPACKETLENGTH; INT16 hardware_MAXPACKETLENGTH;
@ -1189,10 +1186,7 @@ void D_SetDoomcom(void)
{ {
if (doomcom) return; if (doomcom) return;
doomcom = Z_Calloc(sizeof (doomcom_t), PU_STATIC, NULL); doomcom = Z_Calloc(sizeof (doomcom_t), PU_STATIC, NULL);
doomcom->id = DOOMCOM_ID;
doomcom->numslots = doomcom->numnodes = 1; doomcom->numslots = doomcom->numnodes = 1;
doomcom->gametype = 0;
doomcom->consoleplayer = 0;
doomcom->extratics = 0; doomcom->extratics = 0;
} }
@ -1217,7 +1211,6 @@ boolean D_CheckNetGame(void)
I_NetMakeNodewPort = NULL; I_NetMakeNodewPort = NULL;
hardware_MAXPACKETLENGTH = MAXPACKETLENGTH; hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
net_bandwidth = 30000;
// I_InitNetwork sets doomcom and netgame // I_InitNetwork sets doomcom and netgame
// check and initialize the network driver // check and initialize the network driver
multiplayer = false; multiplayer = false;
@ -1237,7 +1230,6 @@ boolean D_CheckNetGame(void)
server = true; // WTF? server always true??? server = true; // WTF? server always true???
// no! The deault mode is server. Client is set elsewhere // no! The deault mode is server. Client is set elsewhere
// when the client executes connect command. // when the client executes connect command.
doomcom->ticdup = 1;
if (M_CheckParm("-extratic")) if (M_CheckParm("-extratic"))
{ {
@ -1248,21 +1240,6 @@ boolean D_CheckNetGame(void)
CONS_Printf(M_GetText("Set extratics to %d\n"), doomcom->extratics); CONS_Printf(M_GetText("Set extratics to %d\n"), doomcom->extratics);
} }
if (M_CheckParm("-bandwidth"))
{
if (M_IsNextParm())
{
net_bandwidth = atoi(M_GetNextParm());
if (net_bandwidth < 1000)
net_bandwidth = 1000;
if (net_bandwidth > 100000)
hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
CONS_Printf(M_GetText("Network bandwidth set to %d\n"), net_bandwidth);
}
else
I_Error("usage: -bandwidth <byte_per_sec>");
}
software_MAXPACKETLENGTH = hardware_MAXPACKETLENGTH; software_MAXPACKETLENGTH = hardware_MAXPACKETLENGTH;
if (M_CheckParm("-packetsize")) if (M_CheckParm("-packetsize"))
{ {
@ -1282,8 +1259,6 @@ boolean D_CheckNetGame(void)
if (netgame) if (netgame)
multiplayer = true; multiplayer = true;
if (doomcom->id != DOOMCOM_ID)
I_Error("Doomcom buffer invalid!");
if (doomcom->numnodes > MAXNETNODES) if (doomcom->numnodes > MAXNETNODES)
I_Error("Too many nodes (%d), max:%d", doomcom->numnodes, MAXNETNODES); I_Error("Too many nodes (%d), max:%d", doomcom->numnodes, MAXNETNODES);
@ -1293,7 +1268,7 @@ boolean D_CheckNetGame(void)
if (M_CheckParm("-debugfile")) if (M_CheckParm("-debugfile"))
{ {
char filename[21]; char filename[21];
INT32 k = doomcom->consoleplayer - 1; INT32 k = consoleplayer - 1;
if (M_IsNextParm()) if (M_IsNextParm())
k = atoi(M_GetNextParm()) - 1; k = atoi(M_GetNextParm()) - 1;
while (!debugfile && k < MAXPLAYERS) while (!debugfile && k < MAXPLAYERS)

View file

@ -1033,7 +1033,6 @@ void FileSendTicker(void)
netbuffer->packettype = PT_FILEFRAGMENT; netbuffer->packettype = PT_FILEFRAGMENT;
// (((sendbytes-nowsentbyte)*TICRATE)/(I_GetTime()-starttime)<(UINT32)net_bandwidth)
while (packetsent-- && filestosend != 0) while (packetsent-- && filestosend != 0)
{ {
for (i = currentnode, j = 0; j < MAXNETNODES; for (i = currentnode, j = 0; j < MAXNETNODES;

View file

@ -32,7 +32,6 @@
#define INETPACKETLENGTH 1024 #define INETPACKETLENGTH 1024
extern INT16 hardware_MAXPACKETLENGTH; extern INT16 hardware_MAXPACKETLENGTH;
extern INT32 net_bandwidth; // in byte/s
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma pack(1) #pragma pack(1)
@ -40,36 +39,17 @@ extern INT32 net_bandwidth; // in byte/s
typedef struct typedef struct
{ {
/// Supposed to be DOOMCOM_ID
INT32 id;
/// SRB2 executes an INT32 to execute commands.
INT16 intnum;
/// Communication between SRB2 and the driver.
/// Is CMD_SEND or CMD_GET.
INT16 command;
/// Is dest for send, set by get (-1 = no packet). /// Is dest for send, set by get (-1 = no packet).
INT16 remotenode; INT16 remotenode;
/// Number of bytes in doomdata to be sent /// Number of bytes in doomdata to be sent
INT16 datalength; INT16 datalength;
/// Info common to all nodes. /// Info common to all nodes.
/// Console is always node 0. /// Console is always node 0.
INT16 numnodes; INT16 numnodes;
/// Flag: 1 = no duplication, 2-5 = dup for slow nets.
INT16 ticdup;
/// Flag: 1 = send a backup tic in every packet. /// Flag: 1 = send a backup tic in every packet.
INT16 extratics; INT16 extratics;
/// kind of game
INT16 gametype;
/// Flag: -1 = new game, 0-5 = load savegame
INT16 savegame;
/// currect map
INT16 map;
/// Info specific to this node.
INT16 consoleplayer;
/// Number of "slots": the highest player number in use plus one. /// Number of "slots": the highest player number in use plus one.
INT16 numslots; INT16 numslots;

View file

@ -37,6 +37,7 @@
#endif #endif
#include "../doomdef.h" #include "../doomdef.h"
#include "../z_zone.h"
#ifdef USE_WINSOCK1 #ifdef USE_WINSOCK1
#include <winsock.h> #include <winsock.h>
@ -87,6 +88,10 @@
#undef EHOSTUNREACH #undef EHOSTUNREACH
#endif #endif
#define EHOSTUNREACH WSAEHOSTUNREACH #define EHOSTUNREACH WSAEHOSTUNREACH
#ifdef ENETUNREACH
#undef ENETUNREACH
#endif
#define ENETUNREACH WSAENETUNREACH
#ifndef IOC_VENDOR #ifndef IOC_VENDOR
#define IOC_VENDOR 0x18000000 #define IOC_VENDOR 0x18000000
#endif #endif
@ -120,8 +125,6 @@ typedef union
static boolean UPNP_support = true; static boolean UPNP_support = true;
#endif // HAVE_MINIUPNC #endif // HAVE_MINIUPNC
#define MAXBANS 100
#include "../i_system.h" #include "../i_system.h"
#include "i_net.h" #include "i_net.h"
#include "d_net.h" #include "d_net.h"
@ -169,8 +172,8 @@ static mysockaddr_t clientaddress[MAXNETNODES+1];
static mysockaddr_t broadcastaddress[MAXNETNODES+1]; static mysockaddr_t broadcastaddress[MAXNETNODES+1];
static size_t broadcastaddresses = 0; static size_t broadcastaddresses = 0;
static boolean nodeconnected[MAXNETNODES+1]; static boolean nodeconnected[MAXNETNODES+1];
static mysockaddr_t banned[MAXBANS]; static mysockaddr_t *banned;
static UINT8 bannedmask[MAXBANS]; static UINT8 *bannedmask;
static size_t numbans = 0; static size_t numbans = 0;
static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1? static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1?
@ -685,7 +688,6 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr
socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6); socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6);
#endif #endif
socklen_t d, da = (socklen_t)sizeof(mysockaddr_t); socklen_t d, da = (socklen_t)sizeof(mysockaddr_t);
ssize_t status;
switch (sockaddr->any.sa_family) switch (sockaddr->any.sa_family)
{ {
@ -696,14 +698,11 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr
default: d = da; break; default: d = da; break;
} }
status = sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d); return sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d);
if (status == -1)
{
CONS_Alert(CONS_WARNING, "Unable to send packet to %s: %s\n", SOCK_AddrToStr(sockaddr), strerror(errno));
}
return status;
} }
#define ALLOWEDERROR(x) ((x) == ECONNREFUSED || (x) == EWOULDBLOCK || (x) == EHOSTUNREACH || (x) == ENETUNREACH)
static void SOCK_Send(void) static void SOCK_Send(void)
{ {
ssize_t c = ERRSOCKET; ssize_t c = ERRSOCKET;
@ -718,19 +717,25 @@ static void SOCK_Send(void)
for (size_t j = 0; j < broadcastaddresses; j++) for (size_t j = 0; j < broadcastaddresses; j++)
{ {
if (myfamily[i] == broadcastaddress[j].any.sa_family) if (myfamily[i] == broadcastaddress[j].any.sa_family)
SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]); {
c = SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]);
if (c == ERRSOCKET && !ALLOWEDERROR(errno))
break;
}
} }
} }
return;
} }
else if (nodesocket[doomcom->remotenode] == (SOCKET_TYPE)ERRSOCKET) else if (nodesocket[doomcom->remotenode] == (SOCKET_TYPE)ERRSOCKET)
{ {
for (size_t i = 0; i < mysocketses; i++) for (size_t i = 0; i < mysocketses; i++)
{ {
if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family) if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family)
SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]); {
c = SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]);
if (c == ERRSOCKET && !ALLOWEDERROR(errno))
break;
}
} }
return;
} }
else else
{ {
@ -740,12 +745,14 @@ static void SOCK_Send(void)
if (c == ERRSOCKET) if (c == ERRSOCKET)
{ {
int e = errno; // save error code so it can't be modified later int e = errno; // save error code so it can't be modified later
if (e != ECONNREFUSED && e != EWOULDBLOCK && e != EHOSTUNREACH) if (!ALLOWEDERROR(e))
I_Error("SOCK_Send, error sending to node %d (%s) #%u: %s", doomcom->remotenode, I_Error("SOCK_Send, error sending to node %d (%s) #%u: %s", doomcom->remotenode,
SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e)); SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e));
} }
} }
#undef ALLOWEDERROR
static void SOCK_FreeNodenum(INT32 numnode) static void SOCK_FreeNodenum(INT32 numnode)
{ {
// can't disconnect from self :) // can't disconnect from self :)
@ -1253,9 +1260,9 @@ static boolean SOCK_Ban(INT32 node)
{ {
if (node > MAXNETNODES) if (node > MAXNETNODES)
return false; return false;
if (numbans == MAXBANS)
return false;
banned = Z_Realloc(banned, sizeof(*banned) * (numbans+1), PU_STATIC, NULL);
bannedmask = Z_Realloc(bannedmask, sizeof(*bannedmask) * (numbans+1), PU_STATIC, NULL);
M_Memcpy(&banned[numbans], &clientaddress[node], sizeof (mysockaddr_t)); M_Memcpy(&banned[numbans], &clientaddress[node], sizeof (mysockaddr_t));
if (banned[numbans].any.sa_family == AF_INET) if (banned[numbans].any.sa_family == AF_INET)
{ {
@ -1278,7 +1285,7 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
struct my_addrinfo *ai, *runp, hints; struct my_addrinfo *ai, *runp, hints;
int gaie; int gaie;
if (numbans == MAXBANS || !address) if (!address)
return false; return false;
memset(&hints, 0x00, sizeof(hints)); memset(&hints, 0x00, sizeof(hints));
@ -1293,8 +1300,10 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
runp = ai; runp = ai;
while(runp != NULL && numbans != MAXBANS) while(runp != NULL)
{ {
banned = Z_Realloc(banned, sizeof(*banned) * (numbans+1), PU_STATIC, NULL);
bannedmask = Z_Realloc(bannedmask, sizeof(*bannedmask) * (numbans+1), PU_STATIC, NULL);
memcpy(&banned[numbans], runp->ai_addr, runp->ai_addrlen); memcpy(&banned[numbans], runp->ai_addr, runp->ai_addrlen);
if (mask) if (mask)
@ -1324,6 +1333,10 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
static void SOCK_ClearBans(void) static void SOCK_ClearBans(void)
{ {
numbans = 0; numbans = 0;
Z_Free(banned);
banned = NULL;
Z_Free(bannedmask);
bannedmask = NULL;
} }
boolean I_InitTcpNetwork(void) boolean I_InitTcpNetwork(void)
@ -1378,7 +1391,6 @@ boolean I_InitTcpNetwork(void)
// FIXME: // FIXME:
// ??? and now ? // ??? and now ?
// server on a big modem ??? 4*isdn // server on a big modem ??? 4*isdn
net_bandwidth = 16000;
hardware_MAXPACKETLENGTH = INETPACKETLENGTH; hardware_MAXPACKETLENGTH = INETPACKETLENGTH;
ret = true; ret = true;
@ -1407,7 +1419,6 @@ boolean I_InitTcpNetwork(void)
// so we're on a LAN // so we're on a LAN
COM_BufAddText("connect any\n"); COM_BufAddText("connect any\n");
net_bandwidth = 800000;
hardware_MAXPACKETLENGTH = MAXPACKETLENGTH; hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
} }
} }

View file

@ -1465,13 +1465,13 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
} }
// check for special pickup // check for special pickup
if (thing->flags & MF_SPECIAL) if (thing->flags & MF_SPECIAL && (tmthing->player || (tmthing->flags & MF_PUSHABLE))) // MF_PUSHABLE added for steam jets
{ {
P_TouchSpecialThing(thing, tmthing, true); // can remove thing P_TouchSpecialThing(thing, tmthing, true); // can remove thing
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;
} }
// check again for special pickup // check again for special pickup
if (tmthing->flags & MF_SPECIAL) if (tmthing->flags & MF_SPECIAL && (thing->player || (thing->flags & MF_PUSHABLE))) // MF_PUSHABLE added for steam jets
{ {
P_TouchSpecialThing(tmthing, thing, true); // can remove thing P_TouchSpecialThing(tmthing, thing, true); // can remove thing
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;

View file

@ -35,6 +35,7 @@
#include "p_polyobj.h" #include "p_polyobj.h"
#include "lua_script.h" #include "lua_script.h"
#include "p_slopes.h" #include "p_slopes.h"
#include "hu_stuff.h"
savedata_t savedata; savedata_t savedata;
@ -4854,6 +4855,12 @@ static void P_NetArchiveMisc(save_t *save_p, boolean resending)
P_WriteUINT8(save_p, 0x2f); P_WriteUINT8(save_p, 0x2f);
else else
P_WriteUINT8(save_p, 0x2e); P_WriteUINT8(save_p, 0x2e);
for (i = 0; i < MAXPLAYERS; i++)
{
P_WriteUINT8(save_p, spam_tokens[i]);
P_WriteUINT32(save_p, spam_tics[i]);
}
} }
static inline boolean P_NetUnArchiveMisc(save_t *save_p, boolean reloading) static inline boolean P_NetUnArchiveMisc(save_t *save_p, boolean reloading)
@ -4951,6 +4958,12 @@ static inline boolean P_NetUnArchiveMisc(save_t *save_p, boolean reloading)
if (P_ReadUINT8(save_p) == 0x2f) if (P_ReadUINT8(save_p) == 0x2f)
paused = true; paused = true;
for (i = 0; i < MAXPLAYERS; i++)
{
spam_tokens[i] = P_ReadUINT8(save_p);
spam_tics[i] = P_ReadUINT32(save_p);
}
return true; return true;
} }

View file

@ -379,7 +379,7 @@ static void MirrorMissingRotations(void)
UINT8 baserotation = GetOppositeRotation(rotation, frame->rotate); UINT8 baserotation = GetOppositeRotation(rotation, frame->rotate);
UINT32 lumpnum = frame->lumppat[baserotation - 1]; UINT32 lumpnum = frame->lumppat[baserotation - 1];
R_InstallSpriteLump(WADFILENUM(lumpnum), LUMPNUM(lumpnum), frame->lumpid[baserotation], framenum, rotation, 1); R_InstallSpriteLump(WADFILENUM(lumpnum), LUMPNUM(lumpnum), frame->lumpid[baserotation - 1], framenum, rotation, 1);
} }
} }
} }

View file

@ -1042,6 +1042,9 @@ static void ST_drawInput(void)
INT32 x = hudinfo[HUD_INPUT].x, y = hudinfo[HUD_INPUT].y; INT32 x = hudinfo[HUD_INPUT].x, y = hudinfo[HUD_INPUT].y;
if (hu_showscores)
return;
if (stplyr->powers[pw_carry] == CR_NIGHTSMODE) if (stplyr->powers[pw_carry] == CR_NIGHTSMODE)
y += 8; y += 8;
else if (modeattacking || !LUA_HudEnabled(hud_lives)) else if (modeattacking || !LUA_HudEnabled(hud_lives))

View file

@ -1329,10 +1329,10 @@ UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlum
/* SLADE is special and puts a single directory entry. Skip that. */ /* SLADE is special and puts a single directory entry. Skip that. */
if (strlen(lump_p->fullname) == name_length) if (strlen(lump_p->fullname) == name_length)
i++; i++;
break; return i;
} }
} }
return i; return INT16_MAX;
} }
// In a PK3 type of resource file, it looks for the next lumpinfo entry that doesn't share the specified pathfile. // In a PK3 type of resource file, it looks for the next lumpinfo entry that doesn't share the specified pathfile.
@ -1350,6 +1350,17 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
return i; return i;
} }
// Returns 0 if the folder is not empty, 1 if it is empty, -1 if it doesn't exist
INT32 W_IsFolderEmpty(const char *name, UINT16 wad)
{
UINT16 start = W_CheckNumForFolderStartPK3(name, wad, 0);
if (start == INT16_MAX)
return -1;
// Unlike W_CheckNumForFolderStartPK3, W_CheckNumForFolderEndPK3 doesn't return INT16_MAX.
return W_CheckNumForFolderEndPK3(name, wad, start) <= start;
}
char *W_GetLumpFolderPathPK3(UINT16 wad, UINT16 lump) char *W_GetLumpFolderPathPK3(UINT16 wad, UINT16 lump)
{ {
const char *fullname = wadfiles[wad]->lumpinfo[lump].fullname; const char *fullname = wadfiles[wad]->lumpinfo[lump].fullname;
@ -1692,7 +1703,7 @@ lumpnum_t W_GetNumForLongName(const char *name)
// //
static UINT16 W_CheckNumForPatchNamePwad(const char *name, UINT16 wad, boolean longname) static UINT16 W_CheckNumForPatchNamePwad(const char *name, UINT16 wad, boolean longname)
{ {
UINT16 i, start, end; UINT16 i, start = INT16_MAX, end = INT16_MAX;
static char uname[8 + 1] = { 0 }; static char uname[8 + 1] = { 0 };
UINT32 hash = 0; UINT32 hash = 0;
lumpinfo_t *lump_p; lumpinfo_t *lump_p;
@ -1714,8 +1725,11 @@ static UINT16 W_CheckNumForPatchNamePwad(const char *name, UINT16 wad, boolean l
// TODO: cache namespace lump IDs // TODO: cache namespace lump IDs
if (W_FileHasFolders(wadfiles[wad])) if (W_FileHasFolders(wadfiles[wad]))
{ {
start = W_CheckNumForFolderStartPK3("Flats/", wad, 0); if (!W_IsFolderEmpty("Flats/", wad))
end = W_CheckNumForFolderEndPK3("Flats/", wad, start); {
start = W_CheckNumForFolderStartPK3("Flats/", wad, 0);
end = W_CheckNumForFolderEndPK3("Flats/", wad, start);
}
} }
else else
{ {

View file

@ -180,6 +180,7 @@ UINT16 W_CheckNumForMarkerStartPwad(const char *name, UINT16 wad, UINT16 startlu
UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump);
UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump);
UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump);
INT32 W_IsFolderEmpty(const char *name, UINT16 wad);
char *W_GetLumpFolderPathPK3(UINT16 wad, UINT16 lump); char *W_GetLumpFolderPathPK3(UINT16 wad, UINT16 lump);
char *W_GetLumpFolderNamePK3(UINT16 wad, UINT16 lump); char *W_GetLumpFolderNamePK3(UINT16 wad, UINT16 lump);