diff --git a/src/d_main.c b/src/d_main.c index cf68ba3d2..a0672bb4e 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -880,6 +880,40 @@ static inline void D_CleanFile(void) } } +///\brief Checks if a netgame URL is being handled, and changes working directory to the EXE's if so. +/// Done because browsers (at least, Firefox on Windows) launch the game from the browser's directory, which causes problems. +static void ChangeDirForUrlHandler(void) +{ + // URL handlers are opened by web browsers (at least Firefox) from the browser's working directory, not the game's stored directory, + // so chdir to that directory unless overridden. + if (M_GetUrlProtocolArg() != NULL && !M_CheckParm("-nochdir")) + { + size_t i; + + CONS_Printf("%s connect links load game files from the SRB2 application's stored directory. Switching to ", SERVER_URL_PROTOCOL); + strlcpy(srb2path, myargv[0], sizeof(srb2path)); + + // Get just the directory, minus the EXE name + for (i = strlen(srb2path)-1; i > 0; i--) + { + if (srb2path[i] == '/' || srb2path[i] == '\\') + { + srb2path[i] = '\0'; + break; + } + } + + CONS_Printf("%s\n", srb2path); + +#if defined (_WIN32) + SetCurrentDirectoryA(srb2path); +#else + if (chdir(srb2path) == -1) + I_OutputMsg("Couldn't change working directory\n"); +#endif + } +} + // ========================================================================== // Identify the SRB2 version, and IWAD file to use. // ========================================================================== @@ -1068,6 +1102,9 @@ void D_SRB2Main(void) // Test Dehacked lists DEH_Check(); + // Netgame URL special case: change working dir to EXE folder. + ChangeDirForUrlHandler(); + // identify the main IWAD file to use IdentifyVersion(); @@ -1158,7 +1195,7 @@ void D_SRB2Main(void) // add any files specified on the command line with -file wadfile // to the wad list - if (!(M_CheckParm("-connect") && !M_CheckParm("-server"))) + if (!((M_GetUrlProtocolArg() || M_CheckParm("-connect")) && !M_CheckParm("-server"))) { if (M_CheckParm("-file")) { @@ -1190,7 +1227,7 @@ void D_SRB2Main(void) M_InitMenuPresTables(); // init title screen display params - if (M_CheckParm("-connect")) + if (M_GetUrlProtocolArg() || M_CheckParm("-connect")) F_InitMenuPresValues(); //---------------------------------------------------- READY TIME diff --git a/src/doomdef.h b/src/doomdef.h index 71c885019..5a5c933e3 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -150,6 +150,9 @@ extern char logfilename[1024]; // Otherwise we can't force updates! #endif +/* A custom URL protocol for server links. */ +#define SERVER_URL_PROTOCOL "srb2://" + // Does this version require an added patch file? // Comment or uncomment this as necessary. #define USE_PATCH_DTA diff --git a/src/i_tcp.c b/src/i_tcp.c index 34cad1765..373ea1bd0 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1423,6 +1423,7 @@ static void SOCK_ClearBans(void) boolean I_InitTcpNetwork(void) { char serverhostname[255]; + const char *urlparam = NULL; boolean ret = false; // initilize the OS's TCP/IP stack if (!I_InitTcpDriver()) @@ -1476,10 +1477,12 @@ boolean I_InitTcpNetwork(void) ret = true; } - else if (M_CheckParm("-connect")) + else if ((urlparam = M_GetUrlProtocolArg()) != NULL || M_CheckParm("-connect")) { - if (M_IsNextParm()) - strcpy(serverhostname, M_GetNextParm()); + if (urlparam != NULL) + strlcpy(serverhostname, urlparam, sizeof(serverhostname)); + else if (M_IsNextParm()) + strlcpy(serverhostname, M_GetNextParm(), sizeof(serverhostname)); else serverhostname[0] = 0; // assuming server in the LAN, use broadcast to detect it diff --git a/src/m_argv.c b/src/m_argv.c index acb74cff4..7d43d96bc 100644 --- a/src/m_argv.c +++ b/src/m_argv.c @@ -34,6 +34,25 @@ boolean myargmalloc = false; */ static INT32 found; +/** \brief Parses a server URL (such as srb2://127.0.0.1) as may be passed to the game via a web browser, etc. + + \return the contents of the URL after the protocol (a server to join), or NULL if not found +*/ +const char *M_GetUrlProtocolArg(void) +{ + INT32 i; + const size_t len = strlen(SERVER_URL_PROTOCOL); + + for (i = 1; i < myargc; i++) + { + if (strlen(myargv[i]) > len && !strnicmp(myargv[i], SERVER_URL_PROTOCOL, len)) + { + return &myargv[i][len]; + } + } + + return NULL; +} /** \brief The M_CheckParm function diff --git a/src/m_argv.h b/src/m_argv.h index ca97d9b12..92770f4e9 100644 --- a/src/m_argv.h +++ b/src/m_argv.h @@ -21,6 +21,9 @@ extern INT32 myargc; extern char **myargv; extern boolean myargmalloc; +// Looks for an srb2:// (or similar) URL passed in as an argument and returns the IP to connect to if found. +const char *M_GetUrlProtocolArg(void); + // Returns the position of the given parameter in the arg list (0 if not found). INT32 M_CheckParm(const char *check);