Merge branch 'discord-menu' into 'master'

Discord Requests menu port

See merge request KartKrew/Kart!1234
This commit is contained in:
Oni 2023-05-15 18:41:21 +00:00
commit 67879b7805
10 changed files with 290 additions and 20 deletions

View file

@ -238,7 +238,7 @@ target_sources(SRB2SDL2 PRIVATE apng.c)
target_link_libraries(SRB2SDL2 PRIVATE DiscordRPC::DiscordRPC)
target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_DISCORDRPC -DUSE_STUN)
target_sources(SRB2SDL2 PRIVATE discord.c stun.c)
target_sources(SRB2SDL2 PRIVATE discord.c stun.cpp)
target_link_libraries(SRB2SDL2 PRIVATE tcbrindle::span)
target_link_libraries(SRB2SDL2 PRIVATE glm)
@ -277,7 +277,7 @@ if(${SRB2_CONFIG_HAVE_DISCORDRPC})
set(SRB2_HAVE_DISCORDRPC ON)
target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_DISCORDRPC)
target_compile_definitions(SRB2SDL2 PRIVATE -DUSE_STUN)
target_sources(SRB2SDL2 PRIVATE discord.c stun.c)
target_sources(SRB2SDL2 PRIVATE discord.c stun.cpp)
else()
message(WARNING "You have specified that Discord Rich Presence is available but it was not found.")
endif()

View file

@ -356,7 +356,7 @@ static void DRPC_GotServerIP(UINT32 address)
--------------------------------------------------*/
static const char *DRPC_GetServerIP(void)
{
const char *address;
const char *address;
// If you're connected
if (I_GetNodeAddress && (address = I_GetNodeAddress(servernode)) != NULL)
@ -403,15 +403,16 @@ static void DRPC_EmptyRequests(void)
--------------------------------------------------*/
void DRPC_UpdatePresence(void)
{
char detailstr[48+1];
#ifdef USEMAPIMG
char mapimg[8+1];
#endif
#ifndef DEVELOP
char detailstr[48+1];
char mapname[5+21+21+2+1];
char charimg[4+SKINNAMESIZE+1];
char charname[11+SKINNAMESIZE+1];
#endif
boolean joinSecretSet = false;
@ -437,10 +438,6 @@ void DRPC_UpdatePresence(void)
discordPresence.largeImageKey = "miscdevelop";
discordPresence.largeImageText = "No peeking!";
discordPresence.state = "Development EXE";
DRPC_EmptyRequests();
Discord_UpdatePresence(&discordPresence);
return;
#endif // DEVELOP
// Server info
@ -462,6 +459,7 @@ void DRPC_UpdatePresence(void)
}
}
#ifndef DEVELOP
if (cv_advertise.value)
{
discordPresence.state = "Public";
@ -470,6 +468,7 @@ void DRPC_UpdatePresence(void)
{
discordPresence.state = "Private";
}
#endif // DEVELOP
discordPresence.partyId = server_context; // Thanks, whoever gave us Mumble support, for implementing the EXACT thing Discord wanted for this field!
discordPresence.partySize = D_NumPlayers(); // Players in server
@ -482,6 +481,7 @@ void DRPC_UpdatePresence(void)
// so that you don't ever end up using bad information from another server.
memset(&discordInfo, 0, sizeof(discordInfo));
#ifndef DEVELOP
// Offline info
if (Playing())
discordPresence.state = "Offline";
@ -489,8 +489,10 @@ void DRPC_UpdatePresence(void)
discordPresence.state = "Watching Replay";
else
discordPresence.state = "Menu";
#endif // DEVELOP
}
#ifndef DEVELOP
// Gametype info
if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING) && Playing())
{
@ -642,6 +644,7 @@ void DRPC_UpdatePresence(void)
snprintf(charname, 28, "Character: %s", skins[players[consoleplayer].skin].realname);
discordPresence.smallImageText = charname; // Character name
}
#endif // DEVELOP
if (joinSecretSet == false)
{

View file

@ -1876,7 +1876,7 @@ static void K_DrawKartPositionNum(INT32 num)
while (num)
{
/*
*/
fx = K_DrawKartPositionNumPatch(
@ -1995,7 +1995,7 @@ static boolean K_drawKartPositionFaces(void)
{
flipflag = V_FLIP|V_VFLIP; // blonic flip
xoff = yoff = 16;
} else
} else
{
flipflag = 0;
xoff = yoff = 0;
@ -5324,3 +5324,24 @@ void K_drawKartHUD(void)
K_DrawDirectorDebugger();
K_DrawGPRankDebugger();
}
void K_DrawSticker(INT32 x, INT32 y, INT32 width, INT32 flags, boolean isSmall)
{
patch_t *stickerEnd;
INT32 height;
if (isSmall == true)
{
stickerEnd = W_CachePatchName("K_STIKE2", PU_CACHE);
height = 6;
}
else
{
stickerEnd = W_CachePatchName("K_STIKEN", PU_CACHE);
height = 11;
}
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, flags, stickerEnd, NULL);
V_DrawFill(x, y, width, height, 24|flags);
V_DrawFixedPatch((x + width)*FRACUNIT, y*FRACUNIT, FRACUNIT, flags|V_FLIP, stickerEnd, NULL);
}

View file

@ -46,6 +46,7 @@ void K_DrawLikeMapThumbnail(fixed_t x, fixed_t y, fixed_t width, UINT32 flags, p
void K_drawTargetHUD(const vector3_t *origin, player_t *player);
void K_drawButton(fixed_t x, fixed_t y, INT32 flags, patch_t *button[2], boolean pressed);
void K_drawButtonAnim(INT32 x, INT32 y, INT32 flags, patch_t *button[2], tic_t animtic);
void K_DrawSticker(INT32 x, INT32 y, INT32 width, INT32 flags, boolean isSmall);
extern patch_t *kp_capsuletarget_arrow[2][2];
extern patch_t *kp_capsuletarget_icon[2];

View file

@ -427,6 +427,10 @@ extern menu_t MISC_StatisticsDef;
extern menuitem_t MISC_SoundTest[];
extern menu_t MISC_SoundTestDef;
#ifdef HAVE_DISCORDRPC
extern menu_t MISC_DiscordRequestsDef;
#endif
// We'll need this since we're gonna have to dynamically enable and disable options depending on which state we're in.
typedef enum
{
@ -1232,6 +1236,20 @@ void M_SoundTest(INT32 choice);
void M_DrawSoundTest(void);
consvar_t *M_GetSoundTestVolumeCvar(void);
#ifdef HAVE_DISCORDRPC
extern struct discordrequestmenu_s {
tic_t ticker;
tic_t confirmDelay;
tic_t confirmLength;
boolean confirmAccept;
boolean removeRequest;
} discordrequestmenu;
void M_DrawDiscordRequests(void);
void M_DiscordRequests(INT32 choice);
const char *M_GetDiscordName(discordRequest_t *r);
#endif
// These defines make it a little easier to make menus
#define DEFAULTMENUSTYLE(source, prev, x, y)\
{\

View file

@ -68,6 +68,10 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
#endif
#ifdef HAVE_DISCORDRPC
#include "discord.h"
#endif
#define SKULLXOFF -32
#define LINEHEIGHT 16
#define STRINGHEIGHT 8
@ -4082,7 +4086,7 @@ void M_DrawPause(void)
y_data_t standings;
memset(&standings, 0, sizeof (standings));
standings.mainplayer = (demo.playback ? displayplayers[0] : consoleplayer);
standings.mainplayer = (demo.playback ? displayplayers[0] : consoleplayer);
// See also G_GetNextMap, Y_CalculateMatchData
if (
@ -4900,7 +4904,7 @@ static void M_DrawChallengePreview(INT32 x, INT32 y)
}
V_DrawThinString(1, BASEVIDHEIGHT-(9+3), V_ALLOWLOWERCASE|V_6WIDTHSPACE, gtname);
break;
}
case SECRET_ENCORE:
@ -5856,3 +5860,94 @@ void M_DrawSoundTest(void)
V_DrawCharacter(cursorx - 4, currentMenu->y - 8 - (skullAnimCounter/5),
'\x1B' | V_SNAPTOTOP|highlightflags, false); // up arrow
}
#ifdef HAVE_DISCORDRPC
void M_DrawDiscordRequests(void)
{
discordRequest_t *curRequest = discordRequestList;
UINT8 *colormap;
patch_t *hand = NULL;
const char *wantText = "...would like to join!";
const char *acceptText = "Accept" ;
const char *declineText = "Decline";
INT32 x = 100;
INT32 y = 133;
INT32 slide = 0;
INT32 maxYSlide = 18;
if (discordrequestmenu.confirmDelay > 0)
{
if (discordrequestmenu.confirmAccept == true)
{
colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_GREEN, GTC_MENUCACHE);
hand = W_CachePatchName("K_LAPH02", PU_CACHE);
}
else
{
colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_RED, GTC_MENUCACHE);
hand = W_CachePatchName("K_LAPH03", PU_CACHE);
}
slide = discordrequestmenu.confirmLength - discordrequestmenu.confirmDelay;
}
else
{
colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_GREY, GTC_MENUCACHE);
}
V_DrawFixedPatch(56*FRACUNIT, 150*FRACUNIT, FRACUNIT, 0, W_CachePatchName("K_LAPE01", PU_CACHE), colormap);
if (hand != NULL)
{
fixed_t handoffset = (4 - abs((signed)(skullAnimCounter - 4))) * FRACUNIT;
V_DrawFixedPatch(56*FRACUNIT, 150*FRACUNIT + handoffset, FRACUNIT, 0, hand, NULL);
}
K_DrawSticker(x + (slide * 32), y - 2, V_ThinStringWidth(M_GetDiscordName(curRequest), V_ALLOWLOWERCASE|V_6WIDTHSPACE), 0, false);
V_DrawThinString(x + (slide * 32), y - 1, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_YELLOWMAP, M_GetDiscordName(curRequest));
K_DrawSticker(x, y + 12, V_ThinStringWidth(wantText, V_ALLOWLOWERCASE|V_6WIDTHSPACE), 0, true);
V_DrawThinString(x, y + 10, V_ALLOWLOWERCASE|V_6WIDTHSPACE, wantText);
INT32 confirmButtonWidth = SHORT(kp_button_a[1][0]->width);
INT32 declineButtonWidth = SHORT(kp_button_b[1][0]->width);
INT32 altDeclineButtonWidth = SHORT(kp_button_x[1][0]->width);
INT32 acceptTextWidth = V_ThinStringWidth(acceptText, V_ALLOWLOWERCASE|V_6WIDTHSPACE);
INT32 declineTextWidth = V_ThinStringWidth(declineText, V_ALLOWLOWERCASE|V_6WIDTHSPACE);
INT32 stickerWidth = (confirmButtonWidth + declineButtonWidth + altDeclineButtonWidth + acceptTextWidth + declineTextWidth);
K_DrawSticker(x, y + 26, stickerWidth, 0, true);
K_drawButtonAnim(x, y + 22, V_SNAPTORIGHT, kp_button_a[1], discordrequestmenu.ticker);
INT32 xoffs = confirmButtonWidth;
V_DrawThinString((x + xoffs), y + 24, V_ALLOWLOWERCASE|V_6WIDTHSPACE, acceptText);
xoffs += acceptTextWidth;
K_drawButtonAnim((x + xoffs), y + 22, V_SNAPTORIGHT, kp_button_b[1], discordrequestmenu.ticker);
xoffs += declineButtonWidth;
K_drawButtonAnim((x + xoffs), y + 22, V_SNAPTORIGHT, kp_button_x[1], discordrequestmenu.ticker);
xoffs += altDeclineButtonWidth;
V_DrawThinString((x + xoffs), y + 24, V_ALLOWLOWERCASE|V_6WIDTHSPACE, declineText);
y -= 18;
while (curRequest->next != NULL)
{
INT32 ySlide = min(slide * 4, maxYSlide);
curRequest = curRequest->next;
K_DrawSticker(x, y - 1 + ySlide, V_ThinStringWidth(M_GetDiscordName(curRequest), V_ALLOWLOWERCASE|V_6WIDTHSPACE), 0, false);
V_DrawThinString(x, y + ySlide, V_ALLOWLOWERCASE|V_6WIDTHSPACE, M_GetDiscordName(curRequest));
y -= 12;
maxYSlide = 12;
}
}
#endif

View file

@ -5,6 +5,7 @@ target_sources(SRB2SDL2 PRIVATE
gametype.c
manual.c
sound-test.c
discord-requests.c
message-box.c
pause-game.c
pause-replay.c

View file

@ -0,0 +1,114 @@
/// \file menus/transient/discord-requests.c
/// \brief Discord Requests menu
#ifdef HAVE_DISCORDRPC
#include "../../k_menu.h"
#include "../../s_sound.h"
#include "../../discord.h"
struct discordrequestmenu_s discordrequestmenu;
static void M_DiscordRequestHandler(INT32 choice)
{
const UINT8 pid = 0;
(void)choice;
if (discordrequestmenu.confirmDelay > 0)
return;
if (M_MenuConfirmPressed(pid))
{
Discord_Respond(discordRequestList->userID, DISCORD_REPLY_YES);
discordrequestmenu.confirmAccept = true;
discordrequestmenu.confirmDelay = discordrequestmenu.confirmLength;
S_StartSound(NULL, sfx_s3k63);
}
else if (M_MenuBackPressed(pid))
{
Discord_Respond(discordRequestList->userID, DISCORD_REPLY_NO);
discordrequestmenu.confirmAccept = false;
discordrequestmenu.confirmDelay = discordrequestmenu.confirmLength;
S_StartSound(NULL, sfx_s3kb2);
}
}
static menuitem_t MISC_DiscordRequests[] =
{
{IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_DiscordRequestHandler}, 0, 0},
};
static void M_DiscordRequestTick(void)
{
discordrequestmenu.ticker++;
if (discordrequestmenu.confirmDelay > 0)
{
discordrequestmenu.confirmDelay--;
if (discordrequestmenu.confirmDelay == 0)
{
discordrequestmenu.removeRequest = true;
}
}
if (discordrequestmenu.removeRequest == true)
{
DRPC_RemoveRequest(discordRequestList);
if (discordRequestList == NULL)
{
// No other requests
PAUSE_Main[mpause_discordrequests].status = IT_DISABLED;
if (currentMenu->prevMenu)
{
M_SetupNextMenu(currentMenu->prevMenu, true);
itemOn = mpause_continue;
}
else
M_ClearMenus(true);
}
discordrequestmenu.removeRequest = false;
}
}
menu_t MISC_DiscordRequestsDef = {
sizeof(MISC_DiscordRequests) / sizeof(menuitem_t),
&PAUSE_MainDef,
0,
MISC_DiscordRequests,
0, 0,
0, 0,
0,
NULL,
0, 0,
M_DrawDiscordRequests,
M_DiscordRequestTick,
NULL,
NULL,
NULL,
};
void M_DiscordRequests(INT32 choice)
{
(void)choice;
static const tic_t confirmLength = 3*TICRATE/4;
discordrequestmenu.confirmLength = confirmLength;
MISC_DiscordRequestsDef.prevMenu = currentMenu;
M_SetupNextMenu(&MISC_DiscordRequestsDef, true);
}
const char *M_GetDiscordName(discordRequest_t *r)
{
if (r == NULL)
return "";
if (cv_discordstreamer.value)
return r->username;
return va("%s#%s", r->username, r->discriminator);
}
#endif // HAVE_DISCORDRPC

View file

@ -6,6 +6,10 @@
#include "../../m_cond.h"
#include "../../s_sound.h"
#ifdef HAVE_DISCORDRPC
#include "../../discord.h"
#endif
// ESC pause menu
// Since there's no descriptions to each item, we'll use the descriptions as the names of the patches we want to draw for each option :)
@ -32,7 +36,7 @@ menuitem_t PAUSE_Main[] =
#ifdef HAVE_DISCORDRPC
{IT_STRING | IT_CALL, "DISCORD REQUESTS", "M_ICODIS",
NULL, {NULL}, 0, 0},
NULL, {.routine = M_DiscordRequests}, 0, 0},
#endif
{IT_STRING | IT_CALL, "RESUME GAME", "M_ICOUNP",
@ -214,6 +218,14 @@ void M_PauseTick(void)
}
else
pausemenu.openoffset /= 2;
#ifdef HAVE_DISCORDRPC
// Show discord requests menu option if any requests are pending
if (discordRequestList)
{
PAUSE_Main[mpause_discordrequests].status = IT_STRING | IT_CALL;
}
#endif
}
boolean M_PauseInputs(INT32 ch)

View file

@ -6,11 +6,13 @@
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file stun.c
/// \file stun.cpp
/// \brief RFC 5389 client implementation to fetch external IP address.
/* https://tools.ietf.org/html/rfc5389 */
#include <vector>
#if defined (__linux__)
#include <sys/random.h>
#elif defined (_WIN32)
@ -33,7 +35,7 @@ consvar_t cv_stunserver = CVAR_INIT (
"stunserver", "stun.l.google.com:19302", CV_SAVE, NULL, NULL
);
static stun_callback_t stun_callback;
static std::vector<stun_callback_t> stun_callbacks;
/* 18.4 STUN UDP and TCP Port Numbers */
@ -125,7 +127,7 @@ STUN_bind (stun_callback_t callback)
memcpy(&doomcom->data[4], &MAGIC_COOKIE, 4U);
memcpy(&doomcom->data[8], transaction_id, 12U);
stun_callback = callback;
stun_callbacks.push_back(callback);
I_NetSend();
Net_CloseConnection(node);/* will handle response at I_NetGet */
@ -137,7 +139,10 @@ STUN_xor_mapped_address (const char * const value)
const UINT32 xaddr = *(const UINT32 *)&value[4];
const UINT32 addr = xaddr ^ MAGIC_COOKIE;
(*stun_callback)(addr);
for (auto &callback : stun_callbacks)
{
callback(addr);
}
return 0U;
}
@ -190,7 +195,7 @@ STUN_got_response
This totals 10 bytes for the attribute.
*/
if (size < 30U || stun_callback == NULL)
if (size < 30U || stun_callbacks.empty())
{
return false;
}
@ -225,7 +230,7 @@ STUN_got_response
while (p < end) ;
}
stun_callback = NULL;
stun_callbacks = {};
return true;
}