mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'rqdx' into 'master'
Roundqueue DX Closes #1411 See merge request KartKrew/Kart!2473
This commit is contained in:
commit
d9bf5d26dd
10 changed files with 797 additions and 302 deletions
146
src/d_clisrv.c
146
src/d_clisrv.c
|
|
@ -4772,6 +4772,149 @@ static void PT_Say(int node)
|
|||
DoSayCommand(say.message, say.target, say.flags, say.source);
|
||||
}
|
||||
|
||||
static void PT_ReqMapQueue(int node)
|
||||
{
|
||||
if (client)
|
||||
return; // Only sent to servers, why are we receiving this?
|
||||
|
||||
reqmapqueue_pak reqmapqueue = netbuffer->u.reqmapqueue;
|
||||
|
||||
// Check for a spoofed source.
|
||||
if (reqmapqueue.source == serverplayer)
|
||||
{
|
||||
// Servers aren't guaranteed to have a playernode, dedis exist.
|
||||
if (node != servernode)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (playernode[reqmapqueue.source] != node)
|
||||
return;
|
||||
|
||||
if (!IsPlayerAdmin(reqmapqueue.source))
|
||||
{
|
||||
CONS_Debug(DBG_NETPLAY,"Received illegal request map queue cmd from Player %d (%s).\n", reqmapqueue.source+1, player_names[reqmapqueue.source]);
|
||||
SendKick(reqmapqueue.source, KICK_MSG_CON_FAIL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const boolean doclear = (reqmapqueue.newgametype == ROUNDQUEUE_CMD_CLEAR);
|
||||
|
||||
// The following prints will only appear when multiple clients
|
||||
// attempt to affect the round queue at similar time increments
|
||||
if (doclear == true)
|
||||
{
|
||||
if (roundqueue.size == 0)
|
||||
{
|
||||
// therefore this one doesn't really need a error print
|
||||
// because what both players wanted was done anyways
|
||||
//CONS_Alert(CONS_ERROR, "queuemap: Queue is already empty!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (reqmapqueue.newgametype == ROUNDQUEUE_CMD_SHOW)
|
||||
{
|
||||
char maprevealmsg[256];
|
||||
if (roundqueue.size == 0)
|
||||
{
|
||||
strlcpy(maprevealmsg, "There are no Rounds queued.", 256);
|
||||
}
|
||||
else if (roundqueue.position >= roundqueue.size)
|
||||
{
|
||||
strlcpy(maprevealmsg, "There are no more Rounds queued!", 256);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *title = G_BuildMapTitle(roundqueue.entries[roundqueue.position].mapnum + 1);
|
||||
|
||||
strlcpy(
|
||||
maprevealmsg,
|
||||
va("The next Round will be on \"%s\".", title),
|
||||
256
|
||||
);
|
||||
|
||||
Z_Free(title);
|
||||
}
|
||||
DoSayCommand(maprevealmsg, 0, HU_SHOUT, servernode);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (roundqueue.size >= ROUNDQUEUE_MAX)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Recieved REQMAPQUEUE, but unable to add map beyond %u\n", roundqueue.size);
|
||||
|
||||
// But this one does, because otherwise it's silent failure!
|
||||
char rejectmsg[256];
|
||||
strlcpy(rejectmsg, "The server couldn't queue your chosen map.", 256);
|
||||
SendServerNotice(reqmapqueue.source, rejectmsg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (reqmapqueue.newmapnum == NEXTMAP_VOTING)
|
||||
{
|
||||
UINT8 numPlayers = 0, i;
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
extern consvar_t cv_forcebots; // debug
|
||||
|
||||
if (!(gametypes[reqmapqueue.newgametype]->rules & GTR_BOTS) && players[i].bot && !cv_forcebots.value)
|
||||
{
|
||||
// Gametype doesn't support bots
|
||||
continue;
|
||||
}
|
||||
|
||||
numPlayers++;
|
||||
}
|
||||
|
||||
reqmapqueue.newmapnum = G_RandMapPerPlayerCount(G_TOLFlag(reqmapqueue.newgametype), UINT16_MAX, false, false, NULL, numPlayers);
|
||||
}
|
||||
|
||||
if (reqmapqueue.newmapnum >= nummapheaders)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Recieved REQMAPQUEUE, but unable to add map of invalid ID (%u)\n", reqmapqueue.newmapnum);
|
||||
|
||||
char rejectmsg[256];
|
||||
strlcpy(rejectmsg, "The server couldn't queue your chosen map.", 256);
|
||||
SendServerNotice(reqmapqueue.source, rejectmsg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
G_AddMapToBuffer(reqmapqueue.newmapnum);
|
||||
|
||||
UINT8 buf[1+2+1];
|
||||
UINT8 *buf_p = buf;
|
||||
|
||||
WRITEUINT8(buf_p, reqmapqueue.flags);
|
||||
WRITEUINT16(buf_p, reqmapqueue.newgametype);
|
||||
|
||||
WRITEUINT8(buf_p, roundqueue.size);
|
||||
|
||||
// Match Got_MapQueuecmd, but with the addition of reqmapqueue.newmapnum available to us
|
||||
if (doclear == true)
|
||||
{
|
||||
memset(&roundqueue, 0, sizeof(struct roundqueue));
|
||||
}
|
||||
else
|
||||
{
|
||||
G_MapIntoRoundQueue(
|
||||
reqmapqueue.newmapnum,
|
||||
reqmapqueue.newgametype,
|
||||
((reqmapqueue.flags & 1) != 0),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
SendNetXCmd(XD_MAPQUEUE, buf, buf_p - buf);
|
||||
}
|
||||
|
||||
static char NodeToSplitPlayer(int node, int split)
|
||||
{
|
||||
if (split == 0)
|
||||
|
|
@ -5117,6 +5260,9 @@ static void HandlePacketFromPlayer(SINT8 node)
|
|||
case PT_SAY:
|
||||
PT_Say(node);
|
||||
break;
|
||||
case PT_REQMAPQUEUE:
|
||||
PT_ReqMapQueue(node);
|
||||
break;
|
||||
case PT_LOGIN:
|
||||
if (client)
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -135,6 +135,8 @@ typedef enum
|
|||
|
||||
PT_SAY, // "Hey server, please send this chat message to everyone via XD_SAY"
|
||||
|
||||
PT_REQMAPQUEUE, // Client requesting a roundqueue operation
|
||||
|
||||
NUMPACKETTYPE
|
||||
} packettype_t;
|
||||
|
||||
|
|
@ -401,6 +403,14 @@ struct say_pak
|
|||
UINT8 source;
|
||||
} ATTRPACK;
|
||||
|
||||
struct reqmapqueue_pak
|
||||
{
|
||||
UINT16 newmapnum;
|
||||
UINT16 newgametype;
|
||||
UINT8 flags;
|
||||
UINT8 source;
|
||||
} ATTRPACK;
|
||||
|
||||
struct netinfo_pak
|
||||
{
|
||||
UINT32 pingtable[MAXPLAYERS+1];
|
||||
|
|
@ -451,6 +461,7 @@ struct doomdata_t
|
|||
responseall_pak responseall; // 256 bytes
|
||||
resultsall_pak resultsall; // 1024 bytes. Also, you really shouldn't trust anything here.
|
||||
say_pak say; // I don't care anymore.
|
||||
reqmapqueue_pak reqmapqueue; // Formerly XD_REQMAPQUEUE
|
||||
} u; // This is needed to pack diff packet types data together
|
||||
} ATTRPACK;
|
||||
|
||||
|
|
|
|||
758
src/d_netcmd.c
758
src/d_netcmd.c
File diff suppressed because it is too large
Load diff
|
|
@ -153,7 +153,7 @@ typedef enum
|
|||
XD_PAUSE, // 9
|
||||
XD_ADDPLAYER, // 10
|
||||
XD_SPECTATE, // 11
|
||||
XD_CLEARSCORES, // 12
|
||||
XD_SETSCORE, // 12
|
||||
XD_VERIFIED, // 13
|
||||
XD_RANDOMSEED, // 14
|
||||
XD_RUNSOC, // 15
|
||||
|
|
@ -180,8 +180,8 @@ typedef enum
|
|||
XD_SCHEDULETASK, // 34
|
||||
XD_SCHEDULECLEAR, // 35
|
||||
XD_AUTOMATE, // 36
|
||||
XD_REQMAPQUEUE, // 37
|
||||
XD_MAPQUEUE, // 38
|
||||
// 37 is free
|
||||
XD_MAPQUEUE = XD_AUTOMATE+2, // 38
|
||||
XD_CALLZVOTE, // 39
|
||||
XD_SETZVOTE, // 40
|
||||
XD_TEAMCHANGE, // 41
|
||||
|
|
|
|||
|
|
@ -38,7 +38,9 @@ extern "C" {
|
|||
// =============================
|
||||
|
||||
#define ROUNDQUEUE_MAX 10 // sane max? maybe make dynamically allocated later
|
||||
#define ROUNDQUEUE_CLEAR UINT16_MAX // lives in gametype field of packets
|
||||
// These two live in gametype field of packets
|
||||
#define ROUNDQUEUE_CMD_CLEAR UINT16_MAX
|
||||
#define ROUNDQUEUE_CMD_SHOW UINT16_MAX-1
|
||||
// The roundqueue itself is resident in g_game.h
|
||||
|
||||
// Selected by user.
|
||||
|
|
|
|||
133
src/g_game.c
133
src/g_game.c
|
|
@ -4406,13 +4406,28 @@ void G_GetNextMap(void)
|
|||
|
||||
if (setalready == false)
|
||||
{
|
||||
UINT8 numPlayers = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
numPlayers++;
|
||||
}
|
||||
|
||||
UINT32 tolflag = G_TOLFlag(gametype);
|
||||
register INT16 cm;
|
||||
|
||||
if (!(gametyperules & GTR_NOCUPSELECT))
|
||||
const boolean cupmode = (!(gametyperules & GTR_NOCUPSELECT));
|
||||
|
||||
nextmap = NEXTMAP_TITLE;
|
||||
|
||||
if (cupmode)
|
||||
{
|
||||
cupheader_t *cup = mapheaderinfo[gamemap-1]->cup;
|
||||
UINT8 gettingresult = 0;
|
||||
cupheader_t *cup = mapheaderinfo[prevmap]->cup;
|
||||
boolean gettingresult = false;
|
||||
|
||||
while (cup)
|
||||
{
|
||||
|
|
@ -4420,7 +4435,7 @@ void G_GetNextMap(void)
|
|||
if (!marathonmode && M_CupLocked(cup))
|
||||
{
|
||||
cup = cup->next;
|
||||
gettingresult = 1;
|
||||
gettingresult = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -4437,6 +4452,35 @@ void G_GetNextMap(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
// If the map is in multiple cups, only consider the first one valid.
|
||||
if (mapheaderinfo[cm]->cup != cup)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!gettingresult)
|
||||
{
|
||||
// Not the map you're on?
|
||||
if (cm == prevmap)
|
||||
{
|
||||
// Ok, this is the current map, time to get the next valid
|
||||
gettingresult = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((mapheaderinfo[cm]->menuflags & LF2_HIDEINMENU) == LF2_HIDEINMENU)
|
||||
{
|
||||
// Not intended to be accessed in multiplayer.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (numPlayers > mapheaderinfo[cm]->playerLimit)
|
||||
{
|
||||
// Too many players for this map.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only care about restrictions if the host is a listen server.
|
||||
if (!dedicated && !marathonmode)
|
||||
{
|
||||
|
|
@ -4462,32 +4506,13 @@ void G_GetNextMap(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
// If the map is in multiple cups, only consider the first one valid.
|
||||
if (mapheaderinfo[cm]->cup != cup)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Grab the first valid after the map you're on
|
||||
if (gettingresult)
|
||||
{
|
||||
nextmap = cm;
|
||||
gettingresult = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Not the map you're on?
|
||||
if (cm != prevmap)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ok, this is the current map, time to get the next
|
||||
gettingresult = 1;
|
||||
}
|
||||
|
||||
// We have a good nextmap?
|
||||
if (gettingresult == 2)
|
||||
if (nextmap < NEXTMAP_SPECIAL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
@ -4495,22 +4520,25 @@ void G_GetNextMap(void)
|
|||
// Ok, iterate to the next
|
||||
cup = cup->next;
|
||||
}
|
||||
|
||||
// Didn't get a nextmap before reaching the end?
|
||||
if (gettingresult != 2)
|
||||
{
|
||||
nextmap = NEXTMAP_CEREMONY; // ceremonymap
|
||||
}
|
||||
|
||||
// Haven't grabbed a nextmap yet?
|
||||
if (nextmap >= NEXTMAP_SPECIAL)
|
||||
{
|
||||
if (cupmode && mapheaderinfo[prevmap]->cup)
|
||||
{
|
||||
// Special case - looking for Lost & Found #1.
|
||||
// Could be anywhere in mapheaderinfo.
|
||||
cm = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cm = prevmap;
|
||||
// All subsequent courses in load order.
|
||||
cm = prevmap+1;
|
||||
}
|
||||
|
||||
do
|
||||
for (; cm < nummapheaders; cm++)
|
||||
{
|
||||
if (++cm >= nummapheaders)
|
||||
cm = 0;
|
||||
|
||||
if (!mapheaderinfo[cm]
|
||||
|| mapheaderinfo[cm]->lumpnum == LUMPERROR
|
||||
|| !(mapheaderinfo[cm]->typeoflevel & tolflag)
|
||||
|
|
@ -4519,6 +4547,24 @@ void G_GetNextMap(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (cupmode && mapheaderinfo[cm]->cup)
|
||||
{
|
||||
// Only Lost & Found this loop around.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((mapheaderinfo[cm]->menuflags & LF2_HIDEINMENU) == LF2_HIDEINMENU)
|
||||
{
|
||||
// Not intended to be accessed in multiplayer.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (numPlayers > mapheaderinfo[cm]->playerLimit)
|
||||
{
|
||||
// Too many players for this map.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only care about restrictions if the host is a listen server.
|
||||
if (!dedicated && !marathonmode)
|
||||
{
|
||||
|
|
@ -4547,10 +4593,9 @@ void G_GetNextMap(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
} while (cm != prevmap);
|
||||
|
||||
nextmap = cm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (K_CanChangeRules(true))
|
||||
|
|
@ -4563,24 +4608,14 @@ void G_GetNextMap(void)
|
|||
nextmap = prevmap;
|
||||
break;
|
||||
case 3: // Voting screen.
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (players[i].spectator)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (i != MAXPLAYERS)
|
||||
if (numPlayers != 0)
|
||||
{
|
||||
nextmap = NEXTMAP_VOTING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case 2: // Go to random map.
|
||||
nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, false, false, NULL);
|
||||
nextmap = G_RandMapPerPlayerCount(G_TOLFlag(gametype), prevmap, false, false, NULL, numPlayers);
|
||||
break;
|
||||
default:
|
||||
if (nextmap >= NEXTMAP_SPECIAL) // Loop back around
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ void Command_Setlives_f(void)
|
|||
D_Cheat(consoleplayer, CHEAT_LIVES, atoi(COM_Argv(1)));
|
||||
}
|
||||
|
||||
void Command_Setscore_f(void)
|
||||
void Command_Setroundscore_f(void)
|
||||
{
|
||||
REQUIRE_CHEATS;
|
||||
REQUIRE_INLEVEL;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ void Command_Savecheckpoint_f(void);
|
|||
void Command_Setrings_f(void);
|
||||
void Command_Setspheres_f(void);
|
||||
void Command_Setlives_f(void);
|
||||
void Command_Setscore_f(void);
|
||||
void Command_Setroundscore_f(void);
|
||||
void Command_Devmode_f(void);
|
||||
void Command_Scale_f(void);
|
||||
void Command_Gravflip_f(void);
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ void M_HandlePauseMenuGametype(INT32 choice)
|
|||
}
|
||||
else // ideally for "random" only, but no sane fallback for "same" and "next"
|
||||
{
|
||||
COM_ImmedExecute(va("randommap -gt %s", gametypes[menugametype]->name));
|
||||
COM_ImmedExecute(va("map -random -gt %s", gametypes[menugametype]->name));
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ TYPEDEF (challengeall_pak);
|
|||
TYPEDEF (responseall_pak);
|
||||
TYPEDEF (resultsall_pak);
|
||||
TYPEDEF (say_pak);
|
||||
TYPEDEF (reqmapqueue_pak);
|
||||
TYPEDEF (netinfo_pak);
|
||||
|
||||
// d_event.h
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue