Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • KartKrew/Kart-Public
  • SteelT/Kart-Public
  • SSNTails/Kart-Public
  • mazmazz_/Kart-Public
  • james/Kart-Public
  • Latius/Kart-Public
  • alphaRexJames/Kart-Public
  • heyjoeway/Kart-Public
  • Namolos/Kart-Public
  • SinnamonLat/Kart-Public
  • filpAM/Kart-Public
  • wolfy852/Kart-Public
  • bird/Kart-Public
  • TehRealSalt/Kart-Public
  • Snu/Kart-Public
  • Tyron/Kart-Public
  • kimmy/Kart-Public
  • Spice/Kart-Public
  • Callmore/Kart-Public
  • JugadorXEI/Kart-Public
  • Fafabis/Kart-Public
  • cspotcode/Kart-Public
  • Lonsfor_/Kart-Public
  • brokenspleentec/Kart-Public
  • minenice/Kart-Public
  • Lighto97/Kart-Public
  • X.organic/Kart-Public
  • Superjustinbros/srb2kart-custom-color-expansion
  • Galactice/Kart-Public
  • haya_/Kart-Public
  • QuantumToasted/Kart-Public
  • Indev/Kart-Public
  • chreas/kart-public-vr
  • alufolie91/Kart-Public2
  • Alam/Kart-Public
  • koi/Kart-Public
  • Alam/kart-public-vr
  • Hanicef/Kart-Public
  • hero0fnin/kart-public-batocera-edit
  • NepDisk/Kart-Public
  • Nep2Disk/Kart-Public
41 results
Select Git revision
Show changes
Commits on Source (83)
...@@ -102,6 +102,11 @@ SINT8 nodetoplayer3[MAXNETNODES]; // say the numplayer for this node if any (spl ...@@ -102,6 +102,11 @@ SINT8 nodetoplayer3[MAXNETNODES]; // say the numplayer for this node if any (spl
SINT8 nodetoplayer4[MAXNETNODES]; // say the numplayer for this node if any (splitscreen == 3) SINT8 nodetoplayer4[MAXNETNODES]; // say the numplayer for this node if any (splitscreen == 3)
UINT8 playerpernode[MAXNETNODES]; // used specialy for splitscreen UINT8 playerpernode[MAXNETNODES]; // used specialy for splitscreen
boolean nodeingame[MAXNETNODES]; // set false as nodes leave game boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
boolean nodedownloadrefuse[MAXNETNODES];
int nodedownloads [MAXNETNODES];
const char *nodedownloadfiles [MAXNETNODES][MAX_WADFILES];
static tic_t nettics[MAXNETNODES]; // what tic the client have received static tic_t nettics[MAXNETNODES]; // what tic the client have received
static tic_t supposedtics[MAXNETNODES]; // nettics prevision for smaller packet static tic_t supposedtics[MAXNETNODES]; // nettics prevision for smaller packet
static UINT8 nodewaiting[MAXNETNODES]; static UINT8 nodewaiting[MAXNETNODES];
...@@ -1332,6 +1337,70 @@ static boolean CL_SendJoin(void) ...@@ -1332,6 +1337,70 @@ static boolean CL_SendJoin(void)
return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak));
} }
void
CopyCaretColors (char *p, const char *s, int n)
{
char *t;
int m;
int c;
if (!n)
return;
while (( t = strchr(s, '^') ))
{
m = ( t - s );
if (m >= n)
{
memcpy(p, s, n);
return;
}
else
memcpy(p, s, m);
p += m;
n -= m;
s += m;
if (!n)
return;
if (s[1])
{
c = toupper(s[1]);
if (isdigit(c))
c = 0x80 + ( c - '0' );
else if (c >= 'A' && c <= 'F')
c = 0x80 + ( c - 'A' );
else
c = 0;
if (c)
{
*p++ = c;
n--;
if (!n)
return;
}
else
{
if (n < 2)
break;
memcpy(p, s, 2);
p += 2;
n -= 2;
}
s += 2;
}
else
break;
}
strncpy(p, s, n);
}
static void SV_SendServerInfo(INT32 node, tic_t servertime) static void SV_SendServerInfo(INT32 node, tic_t servertime)
{ {
UINT8 *p; UINT8 *p;
...@@ -1355,7 +1424,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) ...@@ -1355,7 +1424,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
(D_IsJoinPasswordOn() ? SV_PASSWORD : 0) (D_IsJoinPasswordOn() ? SV_PASSWORD : 0)
); );
strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, CopyCaretColors(netbuffer->u.serverinfo.servername, cv_servername.string,
MAXSERVERNAME); MAXSERVERNAME);
strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7); strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7);
...@@ -2756,20 +2825,6 @@ void CL_Reset(void) ...@@ -2756,20 +2825,6 @@ void CL_Reset(void)
} }
#ifndef NONET #ifndef NONET
static void Command_GetPlayerNum(void)
{
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
{
if (serverplayer == i)
CONS_Printf(M_GetText("num:%2d node:%2d %s\n"), i, playernode[i], player_names[i]);
else
CONS_Printf(M_GetText("\x82num:%2d node:%2d %s\n"), i, playernode[i], player_names[i]);
}
}
SINT8 nametonum(const char *name) SINT8 nametonum(const char *name)
{ {
INT32 playernum, i; INT32 playernum, i;
...@@ -2799,41 +2854,145 @@ SINT8 nametonum(const char *name) ...@@ -2799,41 +2854,145 @@ SINT8 nametonum(const char *name)
return -1; return -1;
} }
/** Lists all players and their player numbers. /** List all players along with a short status.
* *
* \sa Command_GetPlayerNum * \sa Command_NodeTree
*/ */
static void Command_Nodes(void) /*
Formatted like so, with each element separated by space and written on lines:
Two digit player number, colon (:), colored player name, left-aligned.
Then a "status" which is delimited by a double dash (--).
If available, an IP address and port.
Admin status written as "(admin)".
Spectating status written as "(spectator)".
If admin and spectating status both apply and the player's address was not
available, the status is "crammed". If the status is not "crammed", it is
indented the width of " -- self". The intended effect is that the spectating
status aligns with other spectating statuses.
*/
static void Command_ListPlayers(void)
{ {
INT32 i;
size_t maxlen = 0;
const char *address; const char *address;
int width = 0;
for (i = 0; i < MAXPLAYERS; i++) boolean admin;
boolean spectator;
/*
Mode of player status for an individual player (admin, spectator).
1 for admin
2 for spectator
4 for both
*/
int mode = 0;
INT32 totalplayers = 0;
const char *cc;
const char *pcc;
INT32 i;
int n;
for (i = 0; i < MAXPLAYERS; ++i)
if (playeringame[i])
{ {
const size_t plen = strlen(player_names[i]); n = strlen(player_names[i]);
if (playeringame[i] && plen > maxlen) if (n > width)
maxlen = plen; width = n;
if (mode != 7)
{
admin = IsPlayerAdmin(i);
spectator = players[i].spectator;
if (admin)
mode |= 1;
if (spectator)
mode |= 2;
if (admin && spectator)
mode |= 4;
}
} }
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; ++i)
{
if (playeringame[i]) if (playeringame[i])
{ {
CONS_Printf("%.2u: %*s", i, (int)maxlen, player_names[i]); admin = IsPlayerAdmin(i);
CONS_Printf(" - %.2d", playernode[i]); spectator = players[i].spectator;
if (I_GetNodeAddress && (address = I_GetNodeAddress(playernode[i])) != NULL)
CONS_Printf(" - %s", address); if (admin)
cc = "\x85";/* red */
else if (spectator)
cc = "\x86";/* gray */
else
cc = "";
if (IsPlayerAdmin(i)) pcc = V_ApproximateSkinColorCode(players[i].skincolor);
CONS_Printf(M_GetText(" (verified admin)"));
if (players[i].spectator) CONS_Printf("%.2d: ""%s""%-*s""\x80", i, pcc,width, player_names[i]);
CONS_Printf(M_GetText(" (spectator)"));
CONS_Printf("\n"); if (I_GetNodeAddress)
{
if (( address = I_GetNodeAddress(playernode[i]) ))
CONS_Printf(" -- %s", address);
else/* print spacer */
{
/* ...but not if there's a crammed status and were admin */
if (mode != 7 || !admin)
CONS_Printf(" -- ");/* -- self */
}
} }
if (admin)
CONS_Printf(M_GetText("%s"" (admin)"),cc);
if (spectator)
CONS_Printf(M_GetText("%s"" (spectator)"),cc);
CONS_Printf("\n");
totalplayers++;
} }
if (totalplayers == 1)
CONS_Printf("\nThere is 1 player in the game.\n");
else
CONS_Printf("\nThere are %d players in the game.\n", totalplayers);
}
/** Print a table listing all nodes, addresses and associated players.
*
* \sa Command_ListPlayers
*/
static void Command_NodeTree(void)
{
const char *address;
INT32 i;
INT32 totalnodes = 0;
for (i = 0; i < MAXNETNODES; ++i)
if (nodeingame[i])
{
CONS_Printf("* %d", i);
if (playerpernode[i] > 1)
CONS_Printf(" (%d players)", playerpernode[i]);
if (I_GetNodeAddress && ( address = I_GetNodeAddress(i) ))
CONS_Printf(" - %s", address);
CONS_Printf("\n");
#define PRINTPLAYERNODE( prefix, array ) if ((array)[i] > -1) \
CONS_Printf(prefix" (%d) %s\n", (array)[i], player_names[(array)[i]]);
PRINTPLAYERNODE ("|-", nodetoplayer4)
PRINTPLAYERNODE ("|-", nodetoplayer3)
PRINTPLAYERNODE ("|-", nodetoplayer2)
PRINTPLAYERNODE ("\\-", nodetoplayer)
#undef PRINTPLAYERNODE
CONS_Printf("\n");
totalnodes++;
}
CONS_Printf("%d/%d nodes connected.\n", totalnodes, MAXNETNODES);
} }
static void Command_Ban(void) static void Command_Ban(void)
...@@ -3230,6 +3389,13 @@ consvar_t cv_noticedownload = {"noticedownload", "Off", CV_SAVE, CV_OnOff, NULL, ...@@ -3230,6 +3389,13 @@ consvar_t cv_noticedownload = {"noticedownload", "Off", CV_SAVE, CV_OnOff, NULL,
static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0, NULL}}; static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0, NULL}};
consvar_t cv_downloadspeed = {"downloadspeed", "16", CV_SAVE, downloadspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_downloadspeed = {"downloadspeed", "16", CV_SAVE, downloadspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_autoresetdownloads =
{
"autoresetdownloads", "Off",
CV_SAVE,
CV_OnOff
};
static void Got_AddPlayer(UINT8 **p, INT32 playernum); static void Got_AddPlayer(UINT8 **p, INT32 playernum);
static void Got_RemovePlayer(UINT8 **p, INT32 playernum); static void Got_RemovePlayer(UINT8 **p, INT32 playernum);
...@@ -3240,7 +3406,7 @@ void D_ClientServerInit(void) ...@@ -3240,7 +3406,7 @@ void D_ClientServerInit(void)
VERSION/100, VERSION%100, SUBVERSION)); VERSION/100, VERSION%100, SUBVERSION));
#ifndef NONET #ifndef NONET
COM_AddCommand("getplayernum", Command_GetPlayerNum); COM_AddCommand("listplayers", Command_ListPlayers);
COM_AddCommand("kick", Command_Kick); COM_AddCommand("kick", Command_Kick);
COM_AddCommand("ban", Command_Ban); COM_AddCommand("ban", Command_Ban);
COM_AddCommand("banip", Command_BanIP); COM_AddCommand("banip", Command_BanIP);
...@@ -3248,7 +3414,7 @@ void D_ClientServerInit(void) ...@@ -3248,7 +3414,7 @@ void D_ClientServerInit(void)
COM_AddCommand("showbanlist", Command_ShowBan); COM_AddCommand("showbanlist", Command_ShowBan);
COM_AddCommand("reloadbans", Command_ReloadBan); COM_AddCommand("reloadbans", Command_ReloadBan);
COM_AddCommand("connect", Command_connect); COM_AddCommand("connect", Command_connect);
COM_AddCommand("nodes", Command_Nodes); COM_AddCommand("nodetree", Command_NodeTree);
#ifdef PACKETDROP #ifdef PACKETDROP
COM_AddCommand("drop", Command_Drop); COM_AddCommand("drop", Command_Drop);
COM_AddCommand("droprate", Command_Droprate); COM_AddCommand("droprate", Command_Droprate);
...@@ -3485,14 +3651,31 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) ...@@ -3485,14 +3651,31 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
if (netgame) if (netgame)
{ {
if (server && cv_showjoinaddress.value) char *text;
if (server)
{ {
const char *address; const char *address;
if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL) if (cv_showjoinaddress.value &&
HU_AddChatText(va("\x82*Player %d has joined the game (node %d) (%s)", newplayernum+1, node, address), false); // merge join notification + IP to avoid clogging console/chat. I_GetNodeAddress && ( address = I_GetNodeAddress(node) ))
{
text = va(
"\x82*Player %d (num %d) has joined the game (%s)",
newplayernum+1, newplayernum, address);
}
else
{
text = va(
"\x82Player %d (num %d) has joined the game",
newplayernum+1, newplayernum);
}
} }
else else
HU_AddChatText(va("\x82*Player %d has joined the game (node %d)", newplayernum+1, node), false); // if you don't wanna see the join address. {
text = va(
"\x82Player %d has joined the game",
newplayernum+1);
}
HU_AddChatText(text, false);
} }
if (server && multiplayer && motd[0] != '\0') if (server && multiplayer && motd[0] != '\0')
...@@ -3700,6 +3883,104 @@ static void SV_SendRefuse(INT32 node, const char *reason) ...@@ -3700,6 +3883,104 @@ static void SV_SendRefuse(INT32 node, const char *reason)
Net_CloseConnection(node); Net_CloseConnection(node);
} }
/* Macros here 'cause I'm lazy! */
#define MAXVA 1024/* see m_misc.c's va function */
#define MAXMSGLINE 256/* see m_menu.c's M_DrawMessageMenu */
/*
Send a refuse message (like SV_SendRefuse) and include a file list with it.
WARNING: File names will not be truncated, simply left out. The usual message
box background will not display either, due to epic hack.
*/
static void
SV_SendDownloadRefuse (
INT32 node,
const char * reason,
int filec,
const char ** filev)
{
char filename[MAX_WADPATH];
char text[MAXVA];
char * p;
int right;
int i;
int n;
#define SUBTRACT ( p += n, right -= n )
/*
Insert same number of linefeeds before message as after (from the file
list) so that the text doesn't render too high--completely off screen.
*/
n = filec;
memset(text, '\n', n);
/* Initial values for these */
p = text + n;
right = sizeof text - n;/* Count terminating byte anyway, see below. */
/* This is the only text that'll render. */
n = right - 1;
CopyCaretColors(p, reason, n);
p[n] = '\0';
n = strlen(p);
SUBTRACT;
/*
Fill max line length of text box line. This causes the text box drawing
function to fail and print the message to console instead. The text before
this line still renders. This is a very convenient coincidence, and so
I've given myself a pat of the back for this one.
*/
n = MAXMSGLINE + 1;
if (n < right)/* No magic :( */
{
memset(p, '\t', MAXMSGLINE);
p[MAXMSGLINE] = '\n';/* This line can go on forever */
SUBTRACT;
/*
Now just iterate over the files and put them into a list,
with a linefeed after each one, except the last.
*/
for (i = 0; i < filec; ++i)
{
nameonly(strcpy(filename, filev[i]));
n = strlen(filename) + 1;/* plus linefeed */
/* Don't truncate file names, just leave them out. */
if (n > right)
break;
/*
The terminating byte is counted because
truncation here will erase the linefeed.
*/
snprintf(p, right, "%s\n", filename);
SUBTRACT;
}
if (right)/* not if filled out, snprintf did it */
p[-1] = '\0';/* we don't need an extra linefeed */
}
SV_SendRefuse(node, text);
#undef SUBTRACT
}
#undef MAXMSGLINE
#undef MAXVA
// used at txtcmds received to check packetsize bound // used at txtcmds received to check packetsize bound
static size_t TotalTextCmdPerTic(tic_t tic) static size_t TotalTextCmdPerTic(tic_t tic)
{ {
...@@ -3743,6 +4024,26 @@ static void HandleConnect(SINT8 node) ...@@ -3743,6 +4024,26 @@ static void HandleConnect(SINT8 node)
SV_SendRefuse(node, M_GetText("Too many players from\nthis node.")); SV_SendRefuse(node, M_GetText("Too many players from\nthis node."));
else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join? else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join?
SV_SendRefuse(node, M_GetText("No players from\nthis node.")); SV_SendRefuse(node, M_GetText("No players from\nthis node."));
else if (nodedownloadrefuse[node])
{
const char *reason;
char *s;
char *p;
if (( s = strdup(cv_nodownloads.string) ))
{
reason = s;
for (p = s; ( p = strchr(p, '\\') ); ++p)
*p = '\n';
}
else
reason = "You can't download files from this server.\nGo home.";
SV_SendDownloadRefuse(node, reason,
nodedownloads[node], nodedownloadfiles[node]);
free(s);
}
else else
{ {
#ifndef NONET #ifndef NONET
...@@ -3868,12 +4169,15 @@ static void HandleTimeout(SINT8 node) ...@@ -3868,12 +4169,15 @@ static void HandleTimeout(SINT8 node)
*/ */
static void HandleServerInfo(SINT8 node) static void HandleServerInfo(SINT8 node)
{ {
char servername[MAXSERVERNAME];
// compute ping in ms // compute ping in ms
const tic_t ticnow = I_GetTime(); const tic_t ticnow = I_GetTime();
const tic_t ticthen = (tic_t)LONG(netbuffer->u.serverinfo.time); const tic_t ticthen = (tic_t)LONG(netbuffer->u.serverinfo.time);
const tic_t ticdiff = (ticnow - ticthen)*1000/NEWTICRATE; const tic_t ticdiff = (ticnow - ticthen)*1000/NEWTICRATE;
netbuffer->u.serverinfo.time = (tic_t)LONG(ticdiff); netbuffer->u.serverinfo.time = (tic_t)LONG(ticdiff);
netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0; netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0;
memcpy(servername, netbuffer->u.serverinfo.servername, MAXSERVERNAME);
CopyCaretColors(netbuffer->u.serverinfo.servername, servername, MAXSERVERNAME);
netbuffer->u.serverinfo.gametype = (UINT8)((netbuffer->u.serverinfo.gametype == VANILLA_GT_MATCH) ? GT_MATCH : GT_RACE); netbuffer->u.serverinfo.gametype = (UINT8)((netbuffer->u.serverinfo.gametype == VANILLA_GT_MATCH) ? GT_MATCH : GT_RACE);
SL_InsertServer(&netbuffer->u.serverinfo, node); SL_InsertServer(&netbuffer->u.serverinfo, node);
...@@ -4159,7 +4463,7 @@ static void HandlePacketFromAwayNode(SINT8 node) ...@@ -4159,7 +4463,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
case PT_REQUESTFILE: case PT_REQUESTFILE:
if (server) if (server)
{ {
if (!cv_downloading.value || !Got_RequestFilePak(node)) if (( !cv_downloading.value && !*cv_nodownloads.string ) || !Got_RequestFilePak(node))
Net_CloseConnection(node); // close connection if one of the requested files could not be sent, or you disabled downloading anyway Net_CloseConnection(node); // close connection if one of the requested files could not be sent, or you disabled downloading anyway
} }
else else
...@@ -4204,7 +4508,7 @@ static boolean CheckForSpeedHacks(UINT8 p) ...@@ -4204,7 +4508,7 @@ static boolean CheckForSpeedHacks(UINT8 p)
|| netcmds[maketic%BACKUPTICS][p].driftturn > KART_FULLTURN || netcmds[maketic%BACKUPTICS][p].driftturn < -KART_FULLTURN) || netcmds[maketic%BACKUPTICS][p].driftturn > KART_FULLTURN || netcmds[maketic%BACKUPTICS][p].driftturn < -KART_FULLTURN)
{ {
XBOXSTATIC char buf[2]; XBOXSTATIC char buf[2];
CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), playernode[p]); CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from player %d\n"), p);
//D_Clearticcmd(k); //D_Clearticcmd(k);
buf[0] = (char)p; buf[0] = (char)p;
......
...@@ -541,7 +541,8 @@ extern consvar_t ...@@ -541,7 +541,8 @@ extern consvar_t
#ifdef VANILLAJOINNEXTROUND #ifdef VANILLAJOINNEXTROUND
cv_joinnextround, cv_joinnextround,
#endif #endif
cv_netticbuffer, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed; cv_netticbuffer, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed,
cv_autoresetdownloads;
// Used in d_net, the only dependence // Used in d_net, the only dependence
tic_t ExpandTics(INT32 low); tic_t ExpandTics(INT32 low);
...@@ -580,6 +581,8 @@ void D_QuitNetGame(void); ...@@ -580,6 +581,8 @@ void D_QuitNetGame(void);
//? How many ticks to run? //? How many ticks to run?
void TryRunTics(tic_t realtic); void TryRunTics(tic_t realtic);
void CopyCaretColors(char *p, const char *s, int n);
// extra data for lmps // extra data for lmps
// these functions scare me. they contain magic. // these functions scare me. they contain magic.
/*boolean AddLmpExtradata(UINT8 **demo_p, INT32 playernum); /*boolean AddLmpExtradata(UINT8 **demo_p, INT32 playernum);
......
...@@ -110,8 +110,8 @@ UINT8 window_notinfocus = false; ...@@ -110,8 +110,8 @@ UINT8 window_notinfocus = false;
// //
//static INT32 demosequence; //static INT32 demosequence;
static const char *pagename = "MAP1PIC"; static const char *pagename = "MAP1PIC";
static char *startupwadfiles[MAX_WADFILES]; static char *startupwadfiles[MAX_WADFILES][2];
static char *startuppwads[MAX_WADFILES]; static char *startuppwads[MAX_WADFILES][2];
boolean devparm = false; // started game with -devparm boolean devparm = false; // started game with -devparm
...@@ -799,34 +799,46 @@ void D_StartTitle(void) ...@@ -799,34 +799,46 @@ void D_StartTitle(void)
V_SetPaletteLump("PLAYPAL");*/ V_SetPaletteLump("PLAYPAL");*/
} }
static char *
Daddfilestrdup (const char *s)
{
char *p;
if (!( p = strdup(s) ))
{
I_Error("No more free memory to AddFile %s",s);
}
return p;
}
// //
// D_AddFile // D_AddFile
// //
static void D_AddFile(const char *file, char **filearray) static void D_AddFile2(const char *file, const char *lumpname, char *(*filearray)[2])
{ {
size_t pnumwadfiles; size_t pnumwadfiles;
char *newfile;
for (pnumwadfiles = 0; filearray[pnumwadfiles]; pnumwadfiles++) for (pnumwadfiles = 0; filearray[pnumwadfiles][0]; pnumwadfiles++)
; ;
newfile = malloc(strlen(file) + 1); filearray[pnumwadfiles][0] = Daddfilestrdup(file);
if (!newfile) filearray[pnumwadfiles][1] = ( (lumpname) ? Daddfilestrdup(lumpname) : 0 );
{ }
I_Error("No more free memory to AddFile %s",file);
}
strcpy(newfile, file);
filearray[pnumwadfiles] = newfile; static void
D_AddFile (const char *file, char *(*filearray)[2])
{
D_AddFile2(file, 0, filearray);
} }
static inline void D_CleanFile(char **filearray) static inline void D_CleanFile(char *(*filearray)[2])
{ {
size_t pnumwadfiles; size_t pnumwadfiles;
for (pnumwadfiles = 0; filearray[pnumwadfiles]; pnumwadfiles++) for (pnumwadfiles = 0; filearray[pnumwadfiles][0]; pnumwadfiles++)
{ {
free(filearray[pnumwadfiles]); free(filearray[pnumwadfiles][0]);
filearray[pnumwadfiles] = NULL; free(filearray[pnumwadfiles][1]);
filearray[pnumwadfiles][0] = NULL;
filearray[pnumwadfiles][1] = NULL;
} }
} }
...@@ -1144,6 +1156,22 @@ void D_SRB2Main(void) ...@@ -1144,6 +1156,22 @@ void D_SRB2Main(void)
D_AddFile(s, startuppwads); D_AddFile(s, startuppwads);
} }
} }
if (M_CheckParm("-musicfile"))
{
while (M_IsNextParm())
{
const char *f;
const char *u;
f = M_GetNextParm();
u = M_GetNextParm();
if (!u)
{
I_Error("-musicfile missing second name: -musicfile <file> <name>");
}
D_AddFile2(f, u, startuppwads);
}
}
} }
// get map from parms // get map from parms
......
...@@ -714,7 +714,10 @@ void Net_CloseConnection(INT32 node) ...@@ -714,7 +714,10 @@ void Net_CloseConnection(INT32 node)
} }
InitNode(&nodes[node]); InitNode(&nodes[node]);
SV_AbortSendFiles(node); if (cv_autoresetdownloads.value)
CloseNetFile();/* Hack to hopefully reduce lock outs. */
else
SV_AbortSendFiles(node);
I_NetFreeNodenum(node); I_NetFreeNodenum(node);
#endif #endif
} }
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#ifndef __D_NET__ #ifndef __D_NET__
#define __D_NET__ #define __D_NET__
#include "w_wad.h"
// Max computers in a game // Max computers in a game
#define MAXNETNODES (MAXPLAYERS+4) #define MAXNETNODES (MAXPLAYERS+4)
#define BROADCASTADDR MAXNETNODES #define BROADCASTADDR MAXNETNODES
...@@ -41,6 +43,10 @@ extern SINT8 nodetoplayer4[MAXNETNODES]; // Say the numplayer for this node if a ...@@ -41,6 +43,10 @@ extern SINT8 nodetoplayer4[MAXNETNODES]; // Say the numplayer for this node if a
extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen
extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game
extern boolean nodedownloadrefuse[MAXNETNODES];
extern int nodedownloads [MAXNETNODES];
extern const char *nodedownloadfiles [MAXNETNODES][MAX_WADFILES];
INT32 Net_GetFreeAcks(boolean urgent); INT32 Net_GetFreeAcks(boolean urgent);
void Net_AckTicker(void); void Net_AckTicker(void);
......
...@@ -114,6 +114,7 @@ static void BaseNumLaps_OnChange(void); ...@@ -114,6 +114,7 @@ static void BaseNumLaps_OnChange(void);
static void KartFrantic_OnChange(void); static void KartFrantic_OnChange(void);
static void KartSpeed_OnChange(void); static void KartSpeed_OnChange(void);
static void KartEncore_OnChange(void); static void KartEncore_OnChange(void);
static void KartVoteRuleChanges_OnChange(void);
static void KartComeback_OnChange(void); static void KartComeback_OnChange(void);
static void KartEliminateLast_OnChange(void); static void KartEliminateLast_OnChange(void);
...@@ -121,6 +122,13 @@ static void KartEliminateLast_OnChange(void); ...@@ -121,6 +122,13 @@ static void KartEliminateLast_OnChange(void);
static void Fishcake_OnChange(void); static void Fishcake_OnChange(void);
#endif #endif
static void lessvotes_OnChange (void);
static void discardmaps_OnChange (void);
static void Command_resetdownloads_f (void);
static void Command_resetvotebuffer_f (void);
static void Command_hidemap_f (void);
static void Command_Playdemo_f(void); static void Command_Playdemo_f(void);
static void Command_Timedemo_f(void); static void Command_Timedemo_f(void);
static void Command_Stopdemo_f(void); static void Command_Stopdemo_f(void);
...@@ -133,6 +141,7 @@ static void Command_View_f (void); ...@@ -133,6 +141,7 @@ static void Command_View_f (void);
static void Command_SetViews_f(void); static void Command_SetViews_f(void);
static void Command_Addfile(void); static void Command_Addfile(void);
static void Command_Addmusic(void);
static void Command_ListWADS_f(void); static void Command_ListWADS_f(void);
#ifdef DELFILE #ifdef DELFILE
static void Command_Delfile(void); static void Command_Delfile(void);
...@@ -364,7 +373,9 @@ consvar_t cv_kartfrantic = {"kartfrantic", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_ ...@@ -364,7 +373,9 @@ consvar_t cv_kartfrantic = {"kartfrantic", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_
consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}}; static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}};
consvar_t cv_kartvoterulechanges = {"kartvoterulechanges", "Frequent", CV_NETVAR, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartvoterulechanges = {"kartvoterulechanges", "Frequent", CV_NETVAR|CV_CALL|CV_NOINIT, kartvoterulechanges_cons_t, KartVoteRuleChanges_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_kartgametypechanges = {"kartgametypechanges", "Frequent", 0, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_kartencorechance = {"kartencorechance", "Frequent", 0, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}}; static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}};
consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display
static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}}; static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}};
...@@ -463,6 +474,14 @@ consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, ...@@ -463,6 +474,14 @@ consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange,
consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL}; consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL};
consvar_t cv_nodownloads = { "downloadnotice", "", CV_SAVE };
consvar_t cv_lessbattlevotes = {"lessbattlevotes", "No", CV_SAVE, CV_YesNo};
consvar_t cv_lessencorevotes = {"lessencorevotes", "No", CV_SAVE, CV_YesNo};
consvar_t cv_lessvotes = {"lessvotes", "0", CV_SAVE, CV_Unsigned, lessvotes_OnChange};
consvar_t cv_discardmaps = {"discardmaps", "No", CV_SAVE, CV_YesNo, discardmaps_OnChange};
INT16 gametype = GT_RACE; // SRB2kart INT16 gametype = GT_RACE; // SRB2kart
boolean forceresetplayers = false; boolean forceresetplayers = false;
boolean deferencoremode = false; boolean deferencoremode = false;
...@@ -470,6 +489,8 @@ UINT8 splitscreen = 0; ...@@ -470,6 +489,8 @@ UINT8 splitscreen = 0;
boolean circuitmap = true; // SRB2kart boolean circuitmap = true; // SRB2kart
INT32 adminplayers[MAXPLAYERS]; INT32 adminplayers[MAXPLAYERS];
boolean alreadyresetdownloads;
/// \warning Keep this up-to-date if you add/remove/rename net text commands /// \warning Keep this up-to-date if you add/remove/rename net text commands
const char *netxcmdnames[MAXNETXCMD - 1] = const char *netxcmdnames[MAXNETXCMD - 1] =
{ {
...@@ -553,6 +574,12 @@ void D_RegisterServerCommands(void) ...@@ -553,6 +574,12 @@ void D_RegisterServerCommands(void)
RegisterNetXCmd(XD_MODIFYVOTE, Got_ModifyVotecmd); RegisterNetXCmd(XD_MODIFYVOTE, Got_ModifyVotecmd);
RegisterNetXCmd(XD_PICKVOTE, Got_PickVotecmd); RegisterNetXCmd(XD_PICKVOTE, Got_PickVotecmd);
COM_AddCommand("resetdownloads", Command_resetdownloads_f);
COM_AddCommand("resetvotebuffer", Command_resetvotebuffer_f);
COM_AddCommand("hidemap", Command_hidemap_f);
CV_RegisterVar(&cv_nodownloads);
// Remote Administration // Remote Administration
CV_RegisterVar(&cv_dummyjoinpassword); CV_RegisterVar(&cv_dummyjoinpassword);
COM_AddCommand("joinpassword", Command_ChangeJoinPassword_f); COM_AddCommand("joinpassword", Command_ChangeJoinPassword_f);
...@@ -581,6 +608,7 @@ void D_RegisterServerCommands(void) ...@@ -581,6 +608,7 @@ void D_RegisterServerCommands(void)
COM_AddCommand("mapmd5", Command_Mapmd5_f); COM_AddCommand("mapmd5", Command_Mapmd5_f);
COM_AddCommand("addfile", Command_Addfile); COM_AddCommand("addfile", Command_Addfile);
COM_AddCommand("addmusic", Command_Addmusic);
COM_AddCommand("listwad", Command_ListWADS_f); COM_AddCommand("listwad", Command_ListWADS_f);
#ifdef DELFILE #ifdef DELFILE
...@@ -686,6 +714,7 @@ void D_RegisterServerCommands(void) ...@@ -686,6 +714,7 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_maxsend); CV_RegisterVar(&cv_maxsend);
CV_RegisterVar(&cv_noticedownload); CV_RegisterVar(&cv_noticedownload);
CV_RegisterVar(&cv_downloadspeed); CV_RegisterVar(&cv_downloadspeed);
CV_RegisterVar(&cv_autoresetdownloads);
#ifndef NONET #ifndef NONET
CV_RegisterVar(&cv_allownewplayer); CV_RegisterVar(&cv_allownewplayer);
#ifdef VANILLAJOINNEXTROUND #ifdef VANILLAJOINNEXTROUND
...@@ -710,6 +739,12 @@ void D_RegisterServerCommands(void) ...@@ -710,6 +739,12 @@ void D_RegisterServerCommands(void)
#endif #endif
CV_RegisterVar(&cv_dummyconsvar); CV_RegisterVar(&cv_dummyconsvar);
CV_RegisterVar(&cv_lessbattlevotes);
CV_RegisterVar(&cv_lessencorevotes);
CV_RegisterVar(&cv_lessvotes);
CV_RegisterVar(&cv_discardmaps);
} }
// ========================================================================= // =========================================================================
...@@ -848,6 +883,17 @@ void D_RegisterClientCommands(void) ...@@ -848,6 +883,17 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_chatnotifications); CV_RegisterVar(&cv_chatnotifications);
CV_RegisterVar(&cv_chatbacktint); CV_RegisterVar(&cv_chatbacktint);
CV_RegisterVar(&cv_songcredits); CV_RegisterVar(&cv_songcredits);
CV_RegisterVar(&cv_showviewpoint);
CV_RegisterVar(&cv_showfreeplay);
CV_RegisterVar(&cv_playendingmusic);
CV_RegisterVar(&cv_playenginesounds);
CV_RegisterVar(&cv_growmusic);
CV_RegisterVar(&cv_supermusic);
CV_RegisterVar(&cv_growmusicfadein);
CV_RegisterVar(&cv_supermusicfadein);
CV_RegisterVar(&cv_defaultmusicfadein);
CV_RegisterVar(&cv_resumemusic);
CV_RegisterVar(&cv_crossovermusic);
//CV_RegisterVar(&cv_crosshair); //CV_RegisterVar(&cv_crosshair);
//CV_RegisterVar(&cv_crosshair2); //CV_RegisterVar(&cv_crosshair2);
//CV_RegisterVar(&cv_crosshair3); //CV_RegisterVar(&cv_crosshair3);
...@@ -2347,29 +2393,50 @@ void D_SetupVote(void) ...@@ -2347,29 +2393,50 @@ void D_SetupVote(void)
UINT8 buf[6*2]; // five UINT16 maps (at twice the width of a UINT8), and two gametypes UINT8 buf[6*2]; // five UINT16 maps (at twice the width of a UINT8), and two gametypes
UINT8 *p = buf; UINT8 *p = buf;
INT32 i; INT32 i;
UINT8 secondgt = G_SometimesGetDifferentGametype(); UINT8 gt;
UINT8 secondgt;
INT16 votebuffer[3] = {-1,-1,-1}; INT16 votebuffer[3] = {-1,-1,-1};
if (cv_kartencore.value && G_RaceGametype()) if (cv_lessbattlevotes.value && G_BattleGametype())
WRITEUINT8(p, (gametype|0x80)); {
gt = GT_RACE;
secondgt = GT_MATCH;
}
else else
WRITEUINT8(p, gametype); {
gt = gametype;
secondgt = G_SometimesGetDifferentGametype();
if (cv_lessencorevotes.value)
{
if (secondgt == GT_RACE)
secondgt |= 0x80;
}
else
{
if (cv_kartencore.value && G_RaceGametype())
gt |= 0x80;
}
}
WRITEUINT8(p, gt);
WRITEUINT8(p, secondgt); WRITEUINT8(p, secondgt);
gt &= ~0x80;
secondgt &= ~0x80; secondgt &= ~0x80;
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)
{ {
UINT16 m; UINT16 m;
if (i == 2) // sometimes a different gametype if (i == 2) // sometimes a different gametype
m = G_RandMap(G_TOLFlag(secondgt), prevmap, false, 0, true, votebuffer); m = G_RandMap(G_TOLFlag(secondgt), prevmap, prevmapvotes, false, 0, true, votebuffer);
else if (i >= 3) // unknown-random and force-unknown MAP HELL else if (i >= 3) // unknown-random and force-unknown MAP HELL
m = G_RandMap(G_TOLFlag(gametype), prevmap, false, (i-2), (i < 4), votebuffer); m = G_RandMap(G_TOLFlag(gt), prevmap, prevmapvotes, false, (i-2), (i < 4), votebuffer);
else else
m = G_RandMap(G_TOLFlag(gametype), prevmap, false, 0, true, votebuffer); m = G_RandMap(G_TOLFlag(gt), prevmap, prevmapvotes, false, 0, true, votebuffer);
if (i < 3) if (i < 3)
votebuffer[min(i, 2)] = m; // min() is a dumb workaround for gcc 4.4 array-bounds error votebuffer[min(i, 2)] = m; // min() is a dumb workaround for gcc 4.4 array-bounds error
WRITEUINT16(p, m); WRITEUINT16(p, m);
} }
if (cv_lessvotes.value)
memcpy(prevmapvotes, votebuffer, sizeof prevmapvotes);
SendNetXCmd(XD_SETUPVOTE, buf, p - buf); SendNetXCmd(XD_SETUPVOTE, buf, p - buf);
} }
...@@ -3957,7 +4024,7 @@ static void Command_Verify_f(void) ...@@ -3957,7 +4024,7 @@ static void Command_Verify_f(void)
if (COM_Argc() != 2) if (COM_Argc() != 2)
{ {
CONS_Printf(M_GetText("promote <node>: give admin privileges to a node\n")); CONS_Printf(M_GetText("promote <playernum>: give admin privileges to a player\n"));
return; return;
} }
...@@ -4013,7 +4080,7 @@ static void Command_RemoveAdmin_f(void) ...@@ -4013,7 +4080,7 @@ static void Command_RemoveAdmin_f(void)
if (COM_Argc() != 2) if (COM_Argc() != 2)
{ {
CONS_Printf(M_GetText("demote <node>: remove admin privileges from a node\n")); CONS_Printf(M_GetText("demote <playernum>: remove admin privileges from a player\n"));
return; return;
} }
...@@ -4383,7 +4450,7 @@ static void Command_Addfile(void) ...@@ -4383,7 +4450,7 @@ static void Command_Addfile(void)
// Add file on your client directly if it is trivial, or you aren't in a netgame. // Add file on your client directly if it is trivial, or you aren't in a netgame.
if (!(netgame || multiplayer) || musiconly) if (!(netgame || multiplayer) || musiconly)
{ {
P_AddWadFile(fn); P_AddWadFile(fn, 0);
return; return;
} }
...@@ -4432,6 +4499,20 @@ static void Command_Addfile(void) ...@@ -4432,6 +4499,20 @@ static void Command_Addfile(void)
SendNetXCmd(XD_ADDFILE, buf, buf_p - buf); SendNetXCmd(XD_ADDFILE, buf, buf_p - buf);
} }
/** Adds a music pwad at runtime.
*/
static void
Command_Addmusic (void)
{
if (COM_Argc() != 3)
{
CONS_Printf(
"addmusic <file> <name>: load music file, use 6 char. name\n");
return;
}
P_AddWadFile(COM_Argv(1), COM_Argv(2));
}
#ifdef DELFILE #ifdef DELFILE
/** removes the last added pwad at runtime. /** removes the last added pwad at runtime.
* Searches for sounds, maps, music and images to remove * Searches for sounds, maps, music and images to remove
...@@ -4588,7 +4669,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) ...@@ -4588,7 +4669,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
ncs = findfile(filename,md5sum,true); ncs = findfile(filename,md5sum,true);
if (ncs != FS_FOUND || !P_AddWadFile(filename)) if (ncs != FS_FOUND || !P_AddWadFile(filename, 0))
{ {
Command_ExitGame_f(); Command_ExitGame_f();
if (ncs == FS_FOUND) if (ncs == FS_FOUND)
...@@ -4621,6 +4702,7 @@ static void Command_ListWADS_f(void) ...@@ -4621,6 +4702,7 @@ static void Command_ListWADS_f(void)
{ {
INT32 i = numwadfiles; INT32 i = numwadfiles;
char *tempname; char *tempname;
lumpinfo_t *p;
CONS_Printf(M_GetText("There are %d wads loaded:\n"),numwadfiles); CONS_Printf(M_GetText("There are %d wads loaded:\n"),numwadfiles);
for (i--; i >= 0; i--) for (i--; i >= 0; i--)
{ {
...@@ -4632,6 +4714,19 @@ static void Command_ListWADS_f(void) ...@@ -4632,6 +4714,19 @@ static void Command_ListWADS_f(void)
else else
CONS_Printf(" %.2d: %s\n", i, tempname); CONS_Printf(" %.2d: %s\n", i, tempname);
} }
if (wadfiles[WAD_MUSIC])
{
CONS_Printf("There are also %d music files:\n",
wadfiles[WAD_MUSIC]->numlumps);
for (i = 0; i < wadfiles[WAD_MUSIC]->numlumps; ++i)
{
p = &wadfiles[WAD_MUSIC]->lumpinfo[i];
if (strcmp(p->name, p->name2) == 0)
CONS_Printf("%02d: %-8s\n", i, p->name);
else
CONS_Printf("%02d: %-8s (%s)\n", i, p->name, p->name2);
}
}
} }
// ========================================================================= // =========================================================================
...@@ -5860,6 +5955,14 @@ static void KartEncore_OnChange(void) ...@@ -5860,6 +5955,14 @@ static void KartEncore_OnChange(void)
} }
} }
static void KartVoteRuleChanges_OnChange(void)
{
const char *s;
s = cv_kartvoterulechanges.string;
CV_StealthSet(&cv_kartgametypechanges, s);
CV_StealthSet(&cv_kartencorechance, s);
}
static void KartComeback_OnChange(void) static void KartComeback_OnChange(void)
{ {
if (G_BattleGametype()) if (G_BattleGametype())
...@@ -5879,3 +5982,72 @@ static void KartEliminateLast_OnChange(void) ...@@ -5879,3 +5982,72 @@ static void KartEliminateLast_OnChange(void)
if (G_RaceGametype() && cv_karteliminatelast.value) if (G_RaceGametype() && cv_karteliminatelast.value)
P_CheckRacers(); P_CheckRacers();
} }
static void
Command_resetdownloads_f (void)
{
CloseNetFile();
if (server)
{
COM_ImmedExecute("say \"Downloads have been reset.\"");
alreadyresetdownloads = true;
}
}
static void
Command_resetvotebuffer_f (void)
{
prevmap = -1;
lessvotes_OnChange();
discardmaps_OnChange();
}
static void
Command_hidemap_f (void)
{
int ac;
const char *a;
char *title;
int i;
int n;
ac = COM_Argc();
for (i = 1; i < ac; ++i)
{
a = COM_Argv(i);
if (strlen(a) == 2)
{
n = M_MapNumber(a[0], a[1]);
if (n && mapheaderinfo[n-1])
{
mapheaderinfo[n-1]->hidden = ! mapheaderinfo[n-1]->hidden;
title = G_BuildMapTitle(n);
CONS_Printf(
"%s (%s) is %s hidden\n",
title,
G_BuildMapName(n),
( (mapheaderinfo[n-1]->hidden) ?
"now" :
"no longer" ));
}
}
}
}
static void
lessvotes_OnChange (void)
{
prevmapvotes[0] = -1;
prevmapvotes[1] = -1;
prevmapvotes[2] = -1;
}
static void
discardmaps_OnChange (void)
{
int i;
for (i = 0; i < NUMMAPS; ++i)
{
if (mapheaderinfo[i])
mapheaderinfo[i]->already = false;
}
}
...@@ -118,6 +118,8 @@ extern consvar_t cv_kartfrantic; ...@@ -118,6 +118,8 @@ extern consvar_t cv_kartfrantic;
extern consvar_t cv_kartcomeback; extern consvar_t cv_kartcomeback;
extern consvar_t cv_kartencore; extern consvar_t cv_kartencore;
extern consvar_t cv_kartvoterulechanges; extern consvar_t cv_kartvoterulechanges;
extern consvar_t cv_kartgametypechanges;
extern consvar_t cv_kartencorechance;;
extern consvar_t cv_kartspeedometer; extern consvar_t cv_kartspeedometer;
extern consvar_t cv_kartvoices; extern consvar_t cv_kartvoices;
...@@ -151,6 +153,14 @@ extern consvar_t cv_skipmapcheck; ...@@ -151,6 +153,14 @@ extern consvar_t cv_skipmapcheck;
extern consvar_t cv_sleep; extern consvar_t cv_sleep;
extern consvar_t cv_nodownloads;
extern consvar_t cv_lessbattlevotes;
extern consvar_t cv_lessencorevotes;
extern consvar_t cv_lessvotes;
extern consvar_t cv_discardmaps;
typedef enum typedef enum
{ {
XD_NAMEANDCOLOR = 1, XD_NAMEANDCOLOR = 1,
......
...@@ -75,6 +75,7 @@ typedef struct filetx_s ...@@ -75,6 +75,7 @@ typedef struct filetx_s
} id; } id;
UINT32 size; // Size of the file UINT32 size; // Size of the file
UINT8 fileid; UINT8 fileid;
boolean dummy;/* For custom can't download notice; we don't actually send the file! */
INT32 node; // Destination INT32 node; // Destination
struct filetx_s *next; // Next file in the list struct filetx_s *next; // Next file in the list
} filetx_t; } filetx_t;
...@@ -144,12 +145,15 @@ UINT8 *PutFileNeeded(UINT16 firstfile) ...@@ -144,12 +145,15 @@ UINT8 *PutFileNeeded(UINT16 firstfile)
filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS
// Store in the upper four bits // Store in the upper four bits
if (!cv_downloading.value) if (*cv_nodownloads.string)
filestatus += (2 << 4); // Won't send filestatus += (1 << 4);/* This is a hack to get the client to ask for files. */
else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024)) else
filestatus += (1 << 4); // Will send if requested {
// else if (!cv_downloading.value)
// filestatus += (0 << 4); -- Won't send, too big filestatus += (2 << 4); // Won't send
else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024))
filestatus += (1 << 4); // Will send if requested
}
WRITEUINT8(p, filestatus); WRITEUINT8(p, filestatus);
...@@ -325,7 +329,7 @@ boolean Got_RequestFilePak(INT32 node) ...@@ -325,7 +329,7 @@ boolean Got_RequestFilePak(INT32 node)
char wad[MAX_WADPATH+1]; char wad[MAX_WADPATH+1];
UINT8 *p = netbuffer->u.textcmd; UINT8 *p = netbuffer->u.textcmd;
UINT8 id; UINT8 id;
while (p < netbuffer->u.textcmd + MAXTEXTCMD-1) // Don't allow hacked client to overflow while (p < netbuffer->u.textcmd + ( sizeof (doomdata_t) - BASEPACKETSIZE )) // Yeah fuck you
{ {
id = READUINT8(p); id = READUINT8(p);
if (id == 0xFF) if (id == 0xFF)
...@@ -445,7 +449,7 @@ void CL_LoadServerFiles(void) ...@@ -445,7 +449,7 @@ void CL_LoadServerFiles(void)
continue; // Already loaded continue; // Already loaded
else if (fileneeded[i].status == FS_FOUND) else if (fileneeded[i].status == FS_FOUND)
{ {
P_AddWadFile(fileneeded[i].filename); P_AddWadFile(fileneeded[i].filename, 0);
G_SetGameModified(true, false); G_SetGameModified(true, false);
fileneeded[i].status = FS_OPEN; fileneeded[i].status = FS_OPEN;
} }
...@@ -494,9 +498,6 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid) ...@@ -494,9 +498,6 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
INT32 i; INT32 i;
char wadfilename[MAX_WADPATH]; char wadfilename[MAX_WADPATH];
if (cv_noticedownload.value)
CONS_Printf("Sending file \"%s\" to node %d (%s)\n", filename, node, I_GetNodeAddress(node));
// Find the last file in the list and set a pointer to its "next" field // Find the last file in the list and set a pointer to its "next" field
q = &transfer[node].txlist; q = &transfer[node].txlist;
while (*q) while (*q)
...@@ -548,16 +549,32 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid) ...@@ -548,16 +549,32 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
} }
// Handle huge file requests (i.e. bigger than cv_maxsend.value KB) // Handle huge file requests (i.e. bigger than cv_maxsend.value KB)
if (wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024) if (!cv_downloading.value || wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024)
{ {
// Too big if (*cv_nodownloads.string)
// Don't inform client (client sucks, man) {
DEBFILE(va("Client %d request %s: file too big, not sending\n", node, filename)); p->dummy = true;
free(p->id.filename); nodedownloadrefuse[node] = true;
free(p); /* Save file name, we need this */
*q = NULL; nodedownloadfiles[node][nodedownloads[node]++] =
return false; // cancel the rest of the requests wadfiles[i]->filename;
}
else
{
// Too big
// Don't inform client (client sucks, man)
DEBFILE(va("Client %d request %s: file too big, not sending\n", node, filename));
free(p->id.filename);
free(p);
*q = NULL;
return false; // cancel the rest of the requests
}
} }
else
p->dummy = false;
if (cv_noticedownload.value)
CONS_Printf("Sending file \"%s\" to node %d (%s)\n", filename, node, I_GetNodeAddress(node));
DEBFILE(va("Sending file %s (id=%d) to %d\n", filename, fileid, node)); DEBFILE(va("Sending file %s (id=%d) to %d\n", filename, fileid, node));
p->ram = SF_FILE; // It's a file, we need to close it and free its name once we're done sending it p->ram = SF_FILE; // It's a file, we need to close it and free its name once we're done sending it
...@@ -622,7 +639,7 @@ static void SV_EndFileSend(INT32 node) ...@@ -622,7 +639,7 @@ static void SV_EndFileSend(INT32 node)
case SF_FILE: // It's a file, close it and free its filename case SF_FILE: // It's a file, close it and free its filename
if (cv_noticedownload.value) if (cv_noticedownload.value)
CONS_Printf("Ending file transfer for node %d\n", node); CONS_Printf("Ending file transfer for node %d\n", node);
if (transfer[node].currentfile) if (transfer[node].currentfile && !p->dummy)
fclose(transfer[node].currentfile); fclose(transfer[node].currentfile);
free(p->id.filename); free(p->id.filename);
break; break;
...@@ -710,25 +727,33 @@ void SV_FileSendTicker(void) ...@@ -710,25 +727,33 @@ void SV_FileSendTicker(void)
{ {
long filesize; long filesize;
transfer[i].currentfile = if (f->dummy)
fopen(f->id.filename, "rb"); {
f->size = 1;/* client expects at least one byte */
if (!transfer[i].currentfile) transfer[i].currentfile = (FILE *)1;/* (see below) */
I_Error("File %s does not exist", }
f->id.filename); else
{
fseek(transfer[i].currentfile, 0, SEEK_END); transfer[i].currentfile =
filesize = ftell(transfer[i].currentfile); fopen(f->id.filename, "rb");
// Nobody wants to transfer a file bigger if (!transfer[i].currentfile)
// than 4GB! I_Error("File %s does not exist",
if (filesize >= LONG_MAX) f->id.filename);
I_Error("filesize of %s is too large", f->id.filename);
if (filesize == -1) fseek(transfer[i].currentfile, 0, SEEK_END);
I_Error("Error getting filesize of %s", f->id.filename); filesize = ftell(transfer[i].currentfile);
f->size = (UINT32)filesize; // Nobody wants to transfer a file bigger
fseek(transfer[i].currentfile, 0, SEEK_SET); // than 4GB!
if (filesize >= LONG_MAX)
I_Error("filesize of %s is too large", f->id.filename);
if (filesize == -1)
I_Error("Error getting filesize of %s", f->id.filename);
f->size = (UINT32)filesize;
fseek(transfer[i].currentfile, 0, SEEK_SET);
}
} }
else // Sending RAM else // Sending RAM
transfer[i].currentfile = (FILE *)1; // Set currentfile to a non-null value to indicate that it is open transfer[i].currentfile = (FILE *)1; // Set currentfile to a non-null value to indicate that it is open
...@@ -742,6 +767,8 @@ void SV_FileSendTicker(void) ...@@ -742,6 +767,8 @@ void SV_FileSendTicker(void)
size = f->size-transfer[i].position; size = f->size-transfer[i].position;
if (ram) if (ram)
M_Memcpy(p->data, &f->id.ram[transfer[i].position], size); M_Memcpy(p->data, &f->id.ram[transfer[i].position], size);
else if (f->dummy)
p->data[0] = '\n';
else if (fread(p->data, 1, size, transfer[i].currentfile) != size) else if (fread(p->data, 1, size, transfer[i].currentfile) != size)
I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, strerror(ferror(transfer[i].currentfile))); I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, strerror(ferror(transfer[i].currentfile)));
p->position = LONG(transfer[i].position); p->position = LONG(transfer[i].position);
...@@ -760,7 +787,7 @@ void SV_FileSendTicker(void) ...@@ -760,7 +787,7 @@ void SV_FileSendTicker(void)
} }
else else
{ // Not sent for some odd reason, retry at next call { // Not sent for some odd reason, retry at next call
if (!ram) if (!ram && !f->dummy)
fseek(transfer[i].currentfile,transfer[i].position, SEEK_SET); fseek(transfer[i].currentfile,transfer[i].position, SEEK_SET);
// Exit the while (can't send this one so why should i send the next?) // Exit the while (can't send this one so why should i send the next?)
break; break;
...@@ -891,6 +918,8 @@ void SV_AbortSendFiles(INT32 node) ...@@ -891,6 +918,8 @@ void SV_AbortSendFiles(INT32 node)
{ {
while (transfer[node].txlist) while (transfer[node].txlist)
SV_EndFileSend(node); SV_EndFileSend(node);
nodedownloadrefuse[node] = false;
nodedownloads[node] = 0;
} }
void CloseNetFile(void) void CloseNetFile(void)
......
...@@ -151,8 +151,8 @@ extern FILE *logstream; ...@@ -151,8 +151,8 @@ extern FILE *logstream;
#else #else
#define VERSION 110 // Game version #define VERSION 110 // Game version
#define SUBVERSION 0 // more precise version number #define SUBVERSION 0 // more precise version number
#define VERSIONSTRING "v1.1" #define VERSIONSTRING "v1.1 BIRBv3c BETA"
#define VERSIONSTRINGW L"v1.1" #define VERSIONSTRINGW L"v1.1 BIRBv3c BETA"
// Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates! // Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates!
// And change CMakeLists.txt, for CMake users! // And change CMakeLists.txt, for CMake users!
// AND appveyor.yml, for the build bots! // AND appveyor.yml, for the build bots!
......
...@@ -267,6 +267,9 @@ typedef struct ...@@ -267,6 +267,9 @@ typedef struct
// (This is not ifdeffed so the map header structure can stay identical, just in case.) // (This is not ifdeffed so the map header structure can stay identical, just in case.)
UINT8 numCustomOptions; ///< Internal. For Lua custom value support. UINT8 numCustomOptions; ///< Internal. For Lua custom value support.
customoption_t *customopts; ///< Custom options. Allocated dynamically for space reasons. Be careful. customoption_t *customopts; ///< Custom options. Allocated dynamically for space reasons. Be careful.
boolean already;
boolean hidden;
} mapheader_t; } mapheader_t;
// level flags // level flags
...@@ -554,6 +557,8 @@ extern ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; ...@@ -554,6 +557,8 @@ extern ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];
extern INT32 serverplayer; extern INT32 serverplayer;
extern INT32 adminplayers[MAXPLAYERS]; extern INT32 adminplayers[MAXPLAYERS];
extern boolean alreadyresetdownloads;
/// \note put these in d_clisrv outright? /// \note put these in d_clisrv outright?
#endif //__DOOMSTAT__ #endif //__DOOMSTAT__
...@@ -1090,7 +1090,7 @@ void F_TitleScreenTicker(boolean run) ...@@ -1090,7 +1090,7 @@ void F_TitleScreenTicker(boolean run)
return; return;
}*/ }*/
mapname = G_BuildMapName(G_RandMap(TOL_RACE, -2, false, 0, false, NULL)+1); mapname = G_BuildMapName(G_RandMap(TOL_RACE, -2, 0, false, 0, false, NULL)+1);
numstaff = 1; numstaff = 1;
while (numstaff < 99 && (l = W_CheckNumForName(va("%sS%02u",mapname,numstaff+1))) != LUMPERROR) while (numstaff < 99 && (l = W_CheckNumForName(va("%sS%02u",mapname,numstaff+1))) != LUMPERROR)
......
...@@ -327,6 +327,7 @@ demoghost *ghosts = NULL; ...@@ -327,6 +327,7 @@ demoghost *ghosts = NULL;
boolean precache = true; // if true, load all graphics at start boolean precache = true; // if true, load all graphics at start
INT16 prevmap, nextmap; INT16 prevmap, nextmap;
INT16 prevmapvotes[3] = { -1, -1, -1 };
static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}}; static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}};
consvar_t cv_recordmultiplayerdemos = {"netdemo_record", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_recordmultiplayerdemos = {"netdemo_record", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
...@@ -450,6 +451,67 @@ consvar_t cv_pauseifunfocused = {"pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, N ...@@ -450,6 +451,67 @@ consvar_t cv_pauseifunfocused = {"pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, N
// Display song credits // Display song credits
consvar_t cv_songcredits = {"songcredits", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_songcredits = {"songcredits", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// Show "VIEWPOINT:" annonation on HUD
consvar_t cv_showviewpoint = {"showviewpoint", "Yes", CV_SAVE, CV_YesNo, };
// Show "FREE PLAY" when you're alone. :(
consvar_t cv_showfreeplay = { "showfreeplay", "Yes", CV_SAVE, CV_YesNo, };
// Play race finished and battle over music
static CV_PossibleValue_t playendingmusic_cons_t[] = {{0, "Both"}, {1, "Race"}, {2,"Battle"}, {3, "Never"}, {0, NULL}};
consvar_t cv_playendingmusic = {"playendingmusic", "Both", CV_SAVE, playendingmusic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// whirrrr
static CV_PossibleValue_t playenginesounds_cons_t[] =
{
{0, "Never"},
{1, "Rev"},
{2, "Race"},
{3, "Rev+Race"},
{4, "Finish"},
{5, "Rev+Finish"},
{6, "Race+Finish"},
{7, "Always"},
{0, NULL}
};
consvar_t cv_playenginesounds = {"playenginesounds", "Always", CV_SAVE, playenginesounds_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// We can disable special tunes!
consvar_t cv_growmusic = {"growmusic", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_supermusic = {"supermusic", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
/*
Power-ups can fade in!
I made Grow longer than Invinc. because of the shrink.
I made Invinc. shorter than Grow because of the fast paced tune.
*/
consvar_t cv_growmusicfadein =
{
"growmusicfadein", "500",
CV_SAVE, CV_Unsigned,
};
consvar_t cv_supermusicfadein =
{
"supermusicfadein", "300",
CV_SAVE, CV_Unsigned,
};
/* For any other music taking over. (Probably Lua!) */
consvar_t cv_defaultmusicfadein =
{
"defaultfadein", "0",
CV_SAVE, CV_Unsigned,
};
/* Resume level music to the position where it was stopped. */
consvar_t cv_resumemusic = { "resumemusic", "Yes", CV_SAVE, CV_YesNo };
/* Resume from where last level's music left off, if it's the same song. */
consvar_t cv_crossovermusic = { "crossovermusic", "Off", CV_SAVE, CV_OnOff };
/*consvar_t cv_crosshair = {"crosshair", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; /*consvar_t cv_crosshair = {"crosshair", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair2 = {"crosshair2", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_crosshair2 = {"crosshair2", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair3 = {"crosshair3", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_crosshair3 = {"crosshair3", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
...@@ -811,7 +873,7 @@ const char *G_BuildMapName(INT32 map) ...@@ -811,7 +873,7 @@ const char *G_BuildMapName(INT32 map)
map = gamemap-1; map = gamemap-1;
else else
map = prevmap; map = prevmap;
map = G_RandMap(G_TOLFlag(cv_newgametype.value), map, false, 0, false, NULL)+1; map = G_RandMap(G_TOLFlag(cv_newgametype.value), map, 0, false, 0, false, NULL)+1;
} }
if (map < 100) if (map < 100)
...@@ -3382,26 +3444,29 @@ INT16 G_SometimesGetDifferentGametype(void) ...@@ -3382,26 +3444,29 @@ INT16 G_SometimesGetDifferentGametype(void)
{ {
boolean encorepossible = (M_SecretUnlocked(SECRET_ENCORE) && G_RaceGametype()); boolean encorepossible = (M_SecretUnlocked(SECRET_ENCORE) && G_RaceGametype());
if (!cv_kartvoterulechanges.value) // never if (( randmapbuffer[NUMMAPS] > 0 || cv_kartgametypechanges.value == 0 ) &&
return gametype; encorepossible)
if (randmapbuffer[NUMMAPS] > 0 && (encorepossible || cv_kartvoterulechanges.value != 3))
{ {
randmapbuffer[NUMMAPS]--; if (cv_kartgametypechanges.value == 3)
randmapbuffer[NUMMAPS] = 0;/* may not be set from cvar change */
else
randmapbuffer[NUMMAPS]--;
if (encorepossible) if (encorepossible)
{ {
switch (cv_kartvoterulechanges.value) switch (cv_kartencorechance.value)
{ {
case 3: // always case 3: // always
randmapbuffer[NUMMAPS] = 0; // gotta prep this in case it isn't already set encorepossible = true;
break; break;
case 2: // frequent case 2: // frequent
encorepossible = M_RandomChance(FRACUNIT>>1); encorepossible = M_RandomChance(FRACUNIT>>1);
break; break;
case 1: // sometimes case 1: // sometimes
default:
encorepossible = M_RandomChance(FRACUNIT>>2); encorepossible = M_RandomChance(FRACUNIT>>2);
break; break;
default:
encorepossible = false;
} }
if (encorepossible != (boolean)cv_kartencore.value) if (encorepossible != (boolean)cv_kartencore.value)
return (gametype|0x80); return (gametype|0x80);
...@@ -3409,7 +3474,7 @@ INT16 G_SometimesGetDifferentGametype(void) ...@@ -3409,7 +3474,7 @@ INT16 G_SometimesGetDifferentGametype(void)
return gametype; return gametype;
} }
switch (cv_kartvoterulechanges.value) // okay, we're having a gametype change! when's the next one, luv? switch (cv_kartgametypechanges.value) // okay, we're having a gametype change! when's the next one, luv?
{ {
case 3: // always case 3: // always
randmapbuffer[NUMMAPS] = 1; // every other vote (or always if !encorepossible) randmapbuffer[NUMMAPS] = 1; // every other vote (or always if !encorepossible)
...@@ -3422,6 +3487,8 @@ INT16 G_SometimesGetDifferentGametype(void) ...@@ -3422,6 +3487,8 @@ INT16 G_SometimesGetDifferentGametype(void)
case 2: // frequent case 2: // frequent
randmapbuffer[NUMMAPS] = 2; // ...every 1/2th-ish cup? randmapbuffer[NUMMAPS] = 2; // ...every 1/2th-ish cup?
break; break;
case 0: /* never */
return gametype;
} }
if (gametype == GT_MATCH) if (gametype == GT_MATCH)
...@@ -3518,7 +3585,7 @@ static INT32 TOLMaps(INT16 tolflags) ...@@ -3518,7 +3585,7 @@ static INT32 TOLMaps(INT16 tolflags)
* \author Graue <graue@oceanbase.org> * \author Graue <graue@oceanbase.org>
*/ */
static INT16 *okmaps = NULL; static INT16 *okmaps = NULL;
INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer) INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, INT16 *pprevmapbuffer, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer)
{ {
INT32 numokmaps = 0; INT32 numokmaps = 0;
INT16 ix, bufx; INT16 ix, bufx;
...@@ -3550,10 +3617,23 @@ tryagain: ...@@ -3550,10 +3617,23 @@ tryagain:
if ((mapheaderinfo[ix]->typeoflevel & tolflags) != tolflags if ((mapheaderinfo[ix]->typeoflevel & tolflags) != tolflags
|| ix == pprevmap || ix == pprevmap
|| mapheaderinfo[ix]->already
|| mapheaderinfo[ix]->hidden
|| (!dedicated && M_MapLocked(ix+1)) || (!dedicated && M_MapLocked(ix+1))
|| (usehellmaps != (mapheaderinfo[ix]->menuflags & LF2_HIDEINMENU))) // this is bad || (usehellmaps != (mapheaderinfo[ix]->menuflags & LF2_HIDEINMENU))) // this is bad
continue; //isokmap = false; continue; //isokmap = false;
if (pprevmapbuffer)
{
if (
ix == pprevmapbuffer[0] ||
ix == pprevmapbuffer[1] ||
ix == pprevmapbuffer[2]
){
continue;
}
}
if (!ignorebuffer) if (!ignorebuffer)
{ {
if (extbufsize > 0) if (extbufsize > 0)
...@@ -3796,7 +3876,7 @@ static void G_DoCompleted(void) ...@@ -3796,7 +3876,7 @@ static void G_DoCompleted(void)
if (cv_advancemap.value == 0) // Stay on same map. if (cv_advancemap.value == 0) // Stay on same map.
nextmap = prevmap; nextmap = prevmap;
else if (cv_advancemap.value == 2) // Go to random map. else if (cv_advancemap.value == 2) // Go to random map.
nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, false, 0, false, NULL); nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, 0, false, 0, false, NULL);
} }
...@@ -4647,6 +4727,9 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool ...@@ -4647,6 +4727,9 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool
gamemap = (INT16)M_MapNumber(mapname[3], mapname[4]); // get xx out of MAPxx gamemap = (INT16)M_MapNumber(mapname[3], mapname[4]); // get xx out of MAPxx
if (cv_discardmaps.value)
mapheaderinfo[gamemap-1]->already = true;
// gamemap changed; we assume that its map header is always valid, // gamemap changed; we assume that its map header is always valid,
// so make it so // so make it so
if(!mapheaderinfo[gamemap-1]) if(!mapheaderinfo[gamemap-1])
...@@ -4661,6 +4744,9 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool ...@@ -4661,6 +4744,9 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool
automapactive = false; automapactive = false;
imcontinuing = false; imcontinuing = false;
if (server)
alreadyresetdownloads = false;
if (!skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene. if (!skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene.
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer); F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer);
else else
...@@ -6773,7 +6859,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp) ...@@ -6773,7 +6859,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
} }
else else
{ {
P_AddWadFile(filename); P_AddWadFile(filename, 0);
} }
} }
} }
......
...@@ -99,6 +99,7 @@ extern tic_t levelstarttic; ...@@ -99,6 +99,7 @@ extern tic_t levelstarttic;
// for modding? // for modding?
extern INT16 prevmap, nextmap; extern INT16 prevmap, nextmap;
extern INT16 prevmapvotes[3];
extern INT32 gameovertics; extern INT32 gameovertics;
extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard display) extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
extern INT16 rw_maximums[NUM_WEAPONS]; extern INT16 rw_maximums[NUM_WEAPONS];
...@@ -106,6 +107,13 @@ extern INT16 rw_maximums[NUM_WEAPONS]; ...@@ -106,6 +107,13 @@ extern INT16 rw_maximums[NUM_WEAPONS];
// used in game menu // used in game menu
extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection/*, cv_compactscoreboard*/; extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection/*, cv_compactscoreboard*/;
extern consvar_t cv_songcredits; extern consvar_t cv_songcredits;
extern consvar_t cv_showviewpoint;
extern consvar_t cv_showfreeplay;
extern consvar_t cv_playendingmusic;
extern consvar_t cv_playenginesounds;
extern consvar_t cv_growmusic, cv_supermusic;
extern consvar_t cv_growmusicfadein, cv_supermusicfadein, cv_defaultmusicfadein;
extern consvar_t cv_resumemusic, cv_crossovermusic;
extern consvar_t cv_pauseifunfocused; extern consvar_t cv_pauseifunfocused;
//extern consvar_t cv_crosshair, cv_crosshair2, cv_crosshair3, cv_crosshair4; //extern consvar_t cv_crosshair, cv_crosshair2, cv_crosshair3, cv_crosshair4;
extern consvar_t cv_invertmouse/*, cv_alwaysfreelook, cv_chasefreelook, cv_mousemove*/; extern consvar_t cv_invertmouse/*, cv_alwaysfreelook, cv_chasefreelook, cv_mousemove*/;
...@@ -371,7 +379,7 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics); ...@@ -371,7 +379,7 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics);
// Don't split up TOL handling // Don't split up TOL handling
INT16 G_TOLFlag(INT32 pgametype); INT16 G_TOLFlag(INT32 pgametype);
INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer); INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, INT16 *pprevmapbuffer, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer);
void G_AddMapToBuffer(INT16 map); void G_AddMapToBuffer(INT16 map);
#endif #endif
...@@ -499,23 +499,23 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) ...@@ -499,23 +499,23 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
{ {
// what we're gonna do now is check if the node exists // what we're gonna do now is check if the player exists
// with that logic, characters 4 and 5 are our numbers: // with that logic, characters 4 and 5 are our numbers:
const char *newmsg; const char *newmsg;
INT32 spc = 1; // used if nodenum[1] is a space. INT32 spc = 1; // used if playernum[1] is a space.
char *nodenum = (char*) malloc(3); char *playernum = (char*) malloc(3);
strncpy(nodenum, msg+3, 3); strncpy(playernum, msg+3, 3);
// check for undesirable characters in our "number" // check for undesirable characters in our "number"
if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
{ {
// check if nodenum[1] is a space // check if playernum[1] is a space
if (nodenum[1] == ' ') if (playernum[1] == ' ')
spc = 0; spc = 0;
// let it slide // let it slide
else else
{ {
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false); HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
free(nodenum); free(playernum);
return; return;
} }
} }
...@@ -524,14 +524,14 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) ...@@ -524,14 +524,14 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
{ {
if (msg[5] != ' ') if (msg[5] != ' ')
{ {
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false); HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
free(nodenum); free(playernum);
return; return;
} }
} }
target = atoi((const char*) nodenum); // turn that into a number target = atoi((const char*) playernum); // turn that into a number
free(nodenum); free(playernum);
//CONS_Printf("%d\n", target); //CONS_Printf("%d\n", target);
// check for target player, if it doesn't exist then we can't send the message! // check for target player, if it doesn't exist then we can't send the message!
...@@ -645,7 +645,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) ...@@ -645,7 +645,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
UINT8 flags; UINT8 flags;
const char *dispname; const char *dispname;
char *msg; char *msg;
boolean action = false; int action = 0;
char *ptr; char *ptr;
INT32 spam_eatmsg = 0; INT32 spam_eatmsg = 0;
...@@ -729,8 +729,10 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) ...@@ -729,8 +729,10 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
if (target == 0 && strlen(msg) > 4 && strnicmp(msg, "/me ", 4) == 0) if (target == 0 && strlen(msg) > 4 && strnicmp(msg, "/me ", 4) == 0)
{ {
msg += 4; msg += 4;
action = true; action = 1;
} }
else if (strnicmp(msg, "/resetdownloads", 15) == 0)
action = 2;
if (flags & HU_SERVER_SAY) if (flags & HU_SERVER_SAY)
dispname = "SERVER"; dispname = "SERVER";
...@@ -781,145 +783,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) ...@@ -781,145 +783,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
{ {
const UINT8 color = players[playernum].skincolor; const UINT8 color = players[playernum].skincolor;
cstart = "\x83"; cstart = V_ApproximateSkinColorCode(color);
switch (color)
{
case SKINCOLOR_WHITE:
case SKINCOLOR_SILVER:
case SKINCOLOR_SLATE:
cstart = "\x80"; // White
break;
case SKINCOLOR_GREY:
case SKINCOLOR_NICKEL:
case SKINCOLOR_BLACK:
case SKINCOLOR_SKUNK:
case SKINCOLOR_JET:
cstart = "\x86"; // V_GRAYMAP
break;
case SKINCOLOR_SEPIA:
case SKINCOLOR_BEIGE:
case SKINCOLOR_WALNUT:
case SKINCOLOR_BROWN:
case SKINCOLOR_LEATHER:
case SKINCOLOR_RUST:
case SKINCOLOR_WRISTWATCH:
cstart = "\x8e"; // V_BROWNMAP
break;
case SKINCOLOR_FAIRY:
case SKINCOLOR_SALMON:
case SKINCOLOR_PINK:
case SKINCOLOR_ROSE:
case SKINCOLOR_BRICK:
case SKINCOLOR_LEMONADE:
case SKINCOLOR_BUBBLEGUM:
case SKINCOLOR_LILAC:
cstart = "\x8d"; // V_PINKMAP
break;
case SKINCOLOR_CINNAMON:
case SKINCOLOR_RUBY:
case SKINCOLOR_RASPBERRY:
case SKINCOLOR_CHERRY:
case SKINCOLOR_RED:
case SKINCOLOR_CRIMSON:
case SKINCOLOR_MAROON:
case SKINCOLOR_FLAME:
case SKINCOLOR_SCARLET:
case SKINCOLOR_KETCHUP:
cstart = "\x85"; // V_REDMAP
break;
case SKINCOLOR_DAWN:
case SKINCOLOR_SUNSET:
case SKINCOLOR_CREAMSICLE:
case SKINCOLOR_ORANGE:
case SKINCOLOR_PUMPKIN:
case SKINCOLOR_ROSEWOOD:
case SKINCOLOR_BURGUNDY:
case SKINCOLOR_TANGERINE:
cstart = "\x87"; // V_ORANGEMAP
break;
case SKINCOLOR_PEACH:
case SKINCOLOR_CARAMEL:
case SKINCOLOR_CREAM:
cstart = "\x8f"; // V_PEACHMAP
break;
case SKINCOLOR_GOLD:
case SKINCOLOR_ROYAL:
case SKINCOLOR_BRONZE:
case SKINCOLOR_COPPER:
case SKINCOLOR_THUNDER:
cstart = "\x8A"; // V_GOLDMAP
break;
case SKINCOLOR_POPCORN:
case SKINCOLOR_QUARRY:
case SKINCOLOR_YELLOW:
case SKINCOLOR_MUSTARD:
case SKINCOLOR_CROCODILE:
case SKINCOLOR_OLIVE:
cstart = "\x82"; // V_YELLOWMAP
break;
case SKINCOLOR_ARTICHOKE:
case SKINCOLOR_VOMIT:
case SKINCOLOR_GARDEN:
case SKINCOLOR_TEA:
case SKINCOLOR_PISTACHIO:
cstart = "\x8b"; // V_TEAMAP
break;
case SKINCOLOR_LIME:
case SKINCOLOR_HANDHELD:
case SKINCOLOR_MOSS:
case SKINCOLOR_CAMOUFLAGE:
case SKINCOLOR_ROBOHOOD:
case SKINCOLOR_MINT:
case SKINCOLOR_GREEN:
case SKINCOLOR_PINETREE:
case SKINCOLOR_EMERALD:
case SKINCOLOR_SWAMP:
case SKINCOLOR_DREAM:
case SKINCOLOR_PLAGUE:
case SKINCOLOR_ALGAE:
cstart = "\x83"; // V_GREENMAP
break;
case SKINCOLOR_CARIBBEAN:
case SKINCOLOR_AZURE:
case SKINCOLOR_AQUA:
case SKINCOLOR_TEAL:
case SKINCOLOR_CYAN:
case SKINCOLOR_JAWZ:
case SKINCOLOR_CERULEAN:
case SKINCOLOR_NAVY:
case SKINCOLOR_SAPPHIRE:
cstart = "\x88"; // V_SKYMAP
break;
case SKINCOLOR_PIGEON:
case SKINCOLOR_PLATINUM:
case SKINCOLOR_STEEL:
cstart = "\x8c"; // V_STEELMAP
break;
case SKINCOLOR_PERIWINKLE:
case SKINCOLOR_BLUE:
case SKINCOLOR_BLUEBERRY:
case SKINCOLOR_NOVA:
cstart = "\x84"; // V_BLUEMAP
break;
case SKINCOLOR_ULTRAVIOLET:
case SKINCOLOR_PURPLE:
case SKINCOLOR_FUCHSIA:
cstart = "\x81"; // V_PURPLEMAP
break;
case SKINCOLOR_PASTEL:
case SKINCOLOR_MOONSLAM:
case SKINCOLOR_DUSK:
case SKINCOLOR_TOXIC:
case SKINCOLOR_MAUVE:
case SKINCOLOR_LAVENDER:
case SKINCOLOR_BYZANTIUM:
case SKINCOLOR_POMEGRANATE:
cstart = "\x89"; // V_LAVENDERMAP
break;
default:
break;
}
} }
prefix = cstart; prefix = cstart;
...@@ -943,7 +807,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) ...@@ -943,7 +807,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
// Each format includes four strings: color start, display // Each format includes four strings: color start, display
// name, color end, and the message itself. // name, color end, and the message itself.
// '\4' makes the message yellow and beeps; '\3' just beeps. // '\4' makes the message yellow and beeps; '\3' just beeps.
if (action) if (action == 1)
fmt2 = "* %s%s%s%s \x82%s%s"; fmt2 = "* %s%s%s%s \x82%s%s";
else if (target-1 == consoleplayer) // To you else if (target-1 == consoleplayer) // To you
{ {
...@@ -977,6 +841,12 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) ...@@ -977,6 +841,12 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, textcolor, msg), cv_chatnotifications.value); // add to chat HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, textcolor, msg), cv_chatnotifications.value); // add to chat
if (action == 2)
{
if (server && ( IsPlayerAdmin(playernum) || !alreadyresetdownloads ))
COM_ImmedExecute("resetdownloads");
}
if (tempchar) if (tempchar)
Z_Free(tempchar); Z_Free(tempchar);
} }
......
...@@ -575,6 +575,8 @@ void K_RegisterKartStuff(void) ...@@ -575,6 +575,8 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_kartcomeback); CV_RegisterVar(&cv_kartcomeback);
CV_RegisterVar(&cv_kartencore); CV_RegisterVar(&cv_kartencore);
CV_RegisterVar(&cv_kartvoterulechanges); CV_RegisterVar(&cv_kartvoterulechanges);
CV_RegisterVar(&cv_kartgametypechanges);
CV_RegisterVar(&cv_kartencorechance);
CV_RegisterVar(&cv_kartspeedometer); CV_RegisterVar(&cv_kartspeedometer);
CV_RegisterVar(&cv_kartvoices); CV_RegisterVar(&cv_kartvoices);
CV_RegisterVar(&cv_karteliminatelast); CV_RegisterVar(&cv_karteliminatelast);
...@@ -4344,6 +4346,25 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) ...@@ -4344,6 +4346,25 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd)
if (player->kartstuff[k_enginesnd] > 12) if (player->kartstuff[k_enginesnd] > 12)
player->kartstuff[k_enginesnd] = 12; player->kartstuff[k_enginesnd] = 12;
if (cv_playenginesounds.value == -1)
return;
if (!( cv_playenginesounds.value & 1 ))/* not during start */
{
if (leveltime < (starttime + (TICRATE/2)))
return;
}
if (!( cv_playenginesounds.value & 2 ))/* not during race */
{
if (leveltime >= (starttime + (TICRATE/2)) && !player->exiting)
return;
}
if (!( cv_playenginesounds.value & 4 ))/* not during finish */
{
if (player->exiting)
return;
}
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
UINT8 thisvol = 0; UINT8 thisvol = 0;
...@@ -8630,6 +8651,9 @@ void K_drawKartFreePlay(UINT32 flashtime) ...@@ -8630,6 +8651,9 @@ void K_drawKartFreePlay(UINT32 flashtime)
{ {
// no splitscreen support because it's not FREE PLAY if you have more than one player in-game // no splitscreen support because it's not FREE PLAY if you have more than one player in-game
if (! cv_showfreeplay.value)
return;
if ((flashtime % TICRATE) < TICRATE/2) if ((flashtime % TICRATE) < TICRATE/2)
return; return;
......
...@@ -1447,6 +1447,8 @@ static menuitem_t OP_HUDOptionsMenu[] = ...@@ -1447,6 +1447,8 @@ static menuitem_t OP_HUDOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize, 120}, {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize, 120},
{IT_STRING | IT_CVAR, NULL, "Show \"FOCUS LOST\"", &cv_showfocuslost, 135}, {IT_STRING | IT_CVAR, NULL, "Show \"FOCUS LOST\"", &cv_showfocuslost, 135},
{IT_STRING | IT_CVAR, NULL, "Show Viewpoint In Replays", &cv_showviewpoint, 150},
}; };
// Ok it's still called chatoptions but we'll put ping display in here to be clean // Ok it's still called chatoptions but we'll put ping display in here to be clean
...@@ -1496,16 +1498,17 @@ static menuitem_t OP_ServerOptionsMenu[] = ...@@ -1496,16 +1498,17 @@ static menuitem_t OP_ServerOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 40}, {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 40},
{IT_STRING | IT_CVAR, NULL, "Map Progression", &cv_advancemap, 50}, {IT_STRING | IT_CVAR, NULL, "Map Progression", &cv_advancemap, 50},
{IT_STRING | IT_CVAR, NULL, "Voting Timer", &cv_votetime, 60}, {IT_STRING | IT_CVAR, NULL, "Voting Timer", &cv_votetime, 60},
{IT_STRING | IT_CVAR, NULL, "Voting Rule Changes", &cv_kartvoterulechanges, 70}, {IT_STRING | IT_CVAR, NULL, "Voting Gametype Changes", &cv_kartgametypechanges, 70},
{IT_STRING | IT_CVAR, NULL, "Voting Encore Chance", &cv_kartencorechance, 80},
#ifndef NONET #ifndef NONET
{IT_STRING | IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 90}, {IT_STRING | IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 100},
{IT_STRING | IT_CVAR, NULL, "Allow Players to Join", &cv_allownewplayer, 100}, {IT_STRING | IT_CVAR, NULL, "Allow Players to Join", &cv_allownewplayer, 110},
{IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 110}, {IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 120},
{IT_STRING | IT_CVAR, NULL, "Pause Permission", &cv_pause, 120}, {IT_STRING | IT_CVAR, NULL, "Pause Permission", &cv_pause, 130},
{IT_STRING | IT_CVAR, NULL, "Mute All Chat", &cv_mute, 130}, {IT_STRING | IT_CVAR, NULL, "Mute All Chat", &cv_mute, 140},
{IT_SUBMENU|IT_STRING, NULL, "Advanced Options...", &OP_AdvServerOptionsDef,150}, {IT_SUBMENU|IT_STRING, NULL, "Advanced Options...", &OP_AdvServerOptionsDef,160},
#endif #endif
}; };
...@@ -8583,7 +8586,7 @@ static void M_StartServer(INT32 choice) ...@@ -8583,7 +8586,7 @@ static void M_StartServer(INT32 choice)
G_StopMetalDemo(); G_StopMetalDemo();
if (!cv_nextmap.value) if (!cv_nextmap.value)
CV_SetValue(&cv_nextmap, G_RandMap(G_TOLFlag(cv_newgametype.value), -1, false, 0, false, NULL)+1); CV_SetValue(&cv_nextmap, G_RandMap(G_TOLFlag(cv_newgametype.value), -1, 0, false, 0, false, NULL)+1);
if (cv_maxplayers.value < ssplayers+1) if (cv_maxplayers.value < ssplayers+1)
CV_SetValue(&cv_maxplayers, ssplayers+1); CV_SetValue(&cv_maxplayers, ssplayers+1);
......
...@@ -352,7 +352,7 @@ static INT32 GetServersList(void) ...@@ -352,7 +352,7 @@ static INT32 GetServersList(void)
// //
// MS_Connect() // MS_Connect()
// //
static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async) static INT32 MS_SubConnect(const char *ip_addr, const char *str_port, INT32 async, struct sockaddr *bindaddr, socklen_t bindaddrlen)
{ {
#ifdef NONET #ifdef NONET
(void)ip_addr; (void)ip_addr;
...@@ -385,44 +385,48 @@ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async) ...@@ -385,44 +385,48 @@ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async)
socket_fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol); socket_fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
if (socket_fd != (SOCKET_TYPE)ERRSOCKET) if (socket_fd != (SOCKET_TYPE)ERRSOCKET)
{ {
if (async) // do asynchronous connection if (!bindaddr || bind(socket_fd, bindaddr, bindaddrlen) == 0)
{ {
if (async) // do asynchronous connection
{
#ifdef FIONBIO #ifdef FIONBIO
#ifdef WATTCP #ifdef WATTCP
char res = 1; char res = 1;
#else #else
unsigned long res = 1; unsigned long res = 1;
#endif #endif
ioctl(socket_fd, FIONBIO, &res); ioctl(socket_fd, FIONBIO, &res);
#endif #endif
if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) == ERRSOCKET) if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) == ERRSOCKET)
{ {
#ifdef _WIN32 // humm, on win32/win64 it doesn't work with EINPROGRESS (stupid windows) #ifdef _WIN32 // humm, on win32/win64 it doesn't work with EINPROGRESS (stupid windows)
if (WSAGetLastError() != WSAEWOULDBLOCK) if (WSAGetLastError() != WSAEWOULDBLOCK)
#else #else
if (errno != EINPROGRESS) if (errno != EINPROGRESS)
#endif #endif
{ {
con_state = MSCS_FAILED; con_state = MSCS_FAILED;
CloseConnection(); CloseConnection();
I_freeaddrinfo(ai); I_freeaddrinfo(ai);
return MS_CONNECT_ERROR; return MS_CONNECT_ERROR;
}
} }
con_state = MSCS_WAITING;
FD_ZERO(&wset);
FD_SET(socket_fd, &wset);
select_timeout.tv_sec = 0, select_timeout.tv_usec = 0;
I_freeaddrinfo(ai);
return 0;
}
else if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) != ERRSOCKET)
{
I_freeaddrinfo(ai);
return 0;
} }
con_state = MSCS_WAITING;
FD_ZERO(&wset);
FD_SET(socket_fd, &wset);
select_timeout.tv_sec = 0, select_timeout.tv_usec = 0;
I_freeaddrinfo(ai);
return 0;
}
else if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) != ERRSOCKET)
{
I_freeaddrinfo(ai);
return 0;
} }
close(socket_fd);
} }
runp = runp->ai_next; runp = runp->ai_next;
} }
...@@ -431,6 +435,45 @@ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async) ...@@ -431,6 +435,45 @@ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async)
return MS_CONNECT_ERROR; return MS_CONNECT_ERROR;
} }
static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async)
{
const char *lhost;
struct my_addrinfo hints;
struct my_addrinfo *ai, *aip;
int c;
if (M_CheckParm("-bindaddr") && ( lhost = M_GetNextParm() ))
{
memset (&hints, 0x00, sizeof(hints));
#ifdef AI_ADDRCONFIG
hints.ai_flags = AI_ADDRCONFIG;
#endif
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (( c = I_getaddrinfo(lhost, 0, &hints, &ai) ) != 0)
{
CONS_Printf(
"mserv.c: bind to %s: %s\n",
lhost,
gai_strerror(c));
return MS_GETHOSTBYNAME_ERROR;
}
for (aip = ai; aip; aip = aip->ai_next)
{
c = MS_SubConnect(ip_addr, str_port, async, aip->ai_addr, aip->ai_addrlen);
if (c == 0)
{
I_freeaddrinfo(ai);
return 0;
}
}
I_freeaddrinfo(ai);
return c;
}
else
return MS_SubConnect(ip_addr, str_port, async, 0, 0);
}
#define NUM_LIST_SERVER MAXSERVERLIST #define NUM_LIST_SERVER MAXSERVERLIST
const msg_server_t *GetShortServersList(INT32 room) const msg_server_t *GetShortServersList(INT32 room)
{ {
...@@ -748,7 +791,7 @@ static INT32 AddToMasterServer(boolean firstadd) ...@@ -748,7 +791,7 @@ static INT32 AddToMasterServer(boolean firstadd)
strcpy(info->ip, ""); strcpy(info->ip, "");
strcpy(info->port, int2str(current_port)); strcpy(info->port, int2str(current_port));
strcpy(info->name, cv_servername.string); CopyCaretColors(info->name, cv_servername.string, MAXSERVERNAME);
M_Memcpy(&info->room, & room, sizeof (INT32)); M_Memcpy(&info->room, & room, sizeof (INT32));
#if VERSION > 0 || SUBVERSION > 0 #if VERSION > 0 || SUBVERSION > 0
sprintf(info->version, "%d.%d.%d", VERSION/100, VERSION%100, SUBVERSION); sprintf(info->version, "%d.%d.%d", VERSION/100, VERSION%100, SUBVERSION);
......
...@@ -258,6 +258,9 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) ...@@ -258,6 +258,9 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->customopts = NULL; mapheaderinfo[num]->customopts = NULL;
mapheaderinfo[num]->numCustomOptions = 0; mapheaderinfo[num]->numCustomOptions = 0;
mapheaderinfo[num]->already = false;
mapheaderinfo[num]->hidden = false;
DEH_WriteUndoline(va("# uload for map %d", i), NULL, UNDO_DONE); DEH_WriteUndoline(va("# uload for map %d", i), NULL, UNDO_DONE);
} }
...@@ -3357,7 +3360,7 @@ boolean P_RunSOC(const char *socfilename) ...@@ -3357,7 +3360,7 @@ boolean P_RunSOC(const char *socfilename)
lumpnum_t lump; lumpnum_t lump;
if (strstr(socfilename, ".soc") != NULL) if (strstr(socfilename, ".soc") != NULL)
return P_AddWadFile(socfilename); return P_AddWadFile(socfilename, 0);
lump = W_CheckNumForName(socfilename); lump = W_CheckNumForName(socfilename);
if (lump == LUMPERROR) if (lump == LUMPERROR)
...@@ -3373,7 +3376,7 @@ boolean P_RunSOC(const char *socfilename) ...@@ -3373,7 +3376,7 @@ boolean P_RunSOC(const char *socfilename)
// Add a wadfile to the active wad files, // Add a wadfile to the active wad files,
// replace sounds, musics, patches, textures, sprites and maps // replace sounds, musics, patches, textures, sprites and maps
// //
boolean P_AddWadFile(const char *wadfilename) boolean P_AddWadFile(const char *wadfilename, const char *lumpname)
{ {
size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0; size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0;
UINT16 numlumps, wadnum; UINT16 numlumps, wadnum;
...@@ -3383,13 +3386,12 @@ boolean P_AddWadFile(const char *wadfilename) ...@@ -3383,13 +3386,12 @@ boolean P_AddWadFile(const char *wadfilename)
boolean mapsadded = false; boolean mapsadded = false;
boolean replacedcurrentmap = false; boolean replacedcurrentmap = false;
if ((numlumps = W_InitFile(wadfilename)) == INT16_MAX) if ((numlumps = W_InitFile(wadfilename, lumpname, &wadnum)) == INT16_MAX)
{ {
refreshdirmenu |= REFRESHDIR_NOTLOADED; refreshdirmenu |= REFRESHDIR_NOTLOADED;
CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename); CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename);
return false; return false;
} }
else wadnum = (UINT16)(numwadfiles-1);
// //
// search for sound replacements // search for sound replacements
......
...@@ -60,7 +60,7 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); ...@@ -60,7 +60,7 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
#endif #endif
void P_LoadThingsOnly(void); void P_LoadThingsOnly(void);
boolean P_SetupLevel(boolean skipprecip); boolean P_SetupLevel(boolean skipprecip);
boolean P_AddWadFile(const char *wadfilename); boolean P_AddWadFile(const char *wadfilename, const char *lumpname);
#ifdef DELFILE #ifdef DELFILE
boolean P_DelWadFile(void); boolean P_DelWadFile(void);
#endif #endif
......
...@@ -1150,6 +1150,13 @@ boolean P_EndingMusic(player_t *player) ...@@ -1150,6 +1150,13 @@ boolean P_EndingMusic(player_t *player)
if (multiplayer && demo.playback) // Don't play this in multiplayer replays if (multiplayer && demo.playback) // Don't play this in multiplayer replays
return false; return false;
switch (cv_playendingmusic.value)
{
case 1:/* RACE */if (! G_RaceGametype()) return false;
case 2:/* BATTLE */if (! G_BattleGametype()) return false;
case 3:/* NEVER */return false;
}
// Event - Level Finish // Event - Level Finish
// Check for if this is valid or not // Check for if this is valid or not
if (splitscreen) if (splitscreen)
...@@ -1273,10 +1280,10 @@ void P_RestoreMusic(player_t *player) ...@@ -1273,10 +1280,10 @@ void P_RestoreMusic(player_t *player)
} }
// Item - Grow // Item - Grow
if (wantedmus == 2) if (wantedmus == 2 && cv_growmusic.value)
S_ChangeMusicInternal("kgrow", true); S_ChangeMusicInternal("kgrow", true);
// Item - Invincibility // Item - Invincibility
else if (wantedmus == 1) else if (wantedmus == 1 && cv_supermusic.value)
S_ChangeMusicInternal("kinvnc", true); S_ChangeMusicInternal("kinvnc", true);
else else
{ {
......