1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-16 03:23:15 +01:00

Add openrct2:// uri scheme support

This sets up a URI scheme for openrct2 for Windows by adding the necessary registry keys. This is done on startup every time to keep the binary location up to date. URI handling currently supports joining a server.
This commit is contained in:
Ted John
2016-11-12 02:21:42 +00:00
parent 5a850cd155
commit 925d64249f
6 changed files with 145 additions and 1 deletions

View File

@@ -110,4 +110,5 @@ namespace CommandLine
exitcode_t HandleCommandDefault();
exitcode_t HandleCommandConvert(CommandLineArgEnumerator * enumerator);
exitcode_t HandleCommandUri(CommandLineArgEnumerator * enumerator);
}

View File

@@ -126,6 +126,7 @@ const CommandLineCommand CommandLine::RootCommands[]
DefineCommand("set-rct2", "<path>", StandardOptions, HandleCommandSetRCT2),
DefineCommand("convert", "<source> <destination>", StandardOptions, CommandLine::HandleCommandConvert),
DefineCommand("scan-objects", "<path>", StandardOptions, HandleCommandScanObjects),
DefineCommand("handle-uri", "openrct2://.../", StandardOptions, CommandLine::HandleCommandUri),
#if defined(__WINDOWS__) && !defined(__MINGW32__)
DefineCommand("register-shell", "", RegisterShellOptions, HandleCommandRegisterShell),

View File

@@ -0,0 +1,93 @@
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#include "../core/Console.hpp"
#include "../core/Memory.hpp"
#include "../core/String.hpp"
#include "../network/network.h"
#include "CommandLine.hpp"
extern "C"
{
#include "../openrct2.h"
}
static exitcode_t HandleUri(const utf8 * uri);
exitcode_t CommandLine::HandleCommandUri(CommandLineArgEnumerator * enumerator)
{
const utf8 * uri;
if (enumerator->TryPopString(&uri))
{
if (String::StartsWith(uri, "openrct2://"))
{
const utf8 * uriCommand = uri + 11;
return HandleUri(uriCommand);
}
}
Console::Error::WriteLine("Invalid URI");
return EXITCODE_FAIL;
}
static exitcode_t HandleUri(const utf8 * uri)
{
utf8 * * args;
size_t numArgs = String::Split(&args, uri, '/');
if (numArgs > 0)
{
utf8 * arg = args[0];
if (String::Equals(arg, "join"))
{
if (numArgs > 1)
{
utf8 * hostnamePort = args[1];
// Argument is in hostname:port format, so we need to split
utf8 * hostname = String::Duplicate(hostnamePort);
sint32 port = NETWORK_DEFAULT_PORT;
size_t colonIndex = String::IndexOf(hostnamePort, ':');
if (colonIndex != SIZE_MAX)
{
Memory::Free(hostname);
hostname = String::Substring(hostnamePort, 0, colonIndex);
port = atoi(hostnamePort + colonIndex + 1);
}
// Set the network start configuration
gNetworkStart = NETWORK_MODE_CLIENT;
String::Set(gNetworkStartHost, sizeof(gNetworkStartHost), hostname);
gNetworkStartPort = port;
Memory::Free(hostname);
}
else
{
Console::Error::WriteLine("Expected hostname:port after join");
return EXITCODE_FAIL;
}
}
}
// Clean up
for (size_t i = 0; i < numArgs; i++)
{
Memory::Free(args[i]);
}
Memory::FreeArray(args, numArgs);
return EXITCODE_CONTINUE;
}

View File

@@ -72,6 +72,7 @@
<ClCompile Include="audio\FileAudioSource.cpp" />
<ClCompile Include="audio\MemoryAudioSource.cpp" />
<ClCompile Include="audio\NullAudioSource.cpp" />
<ClCompile Include="cmdline\UriHandler.cpp" />
<ClCompile Include="config\Config.cpp" />
<ClCompile Include="config\IniReader.cpp" />
<ClCompile Include="config\IniWriter.cpp" />

View File

@@ -224,6 +224,7 @@ void core_init();
HWND windows_get_window_handle();
void platform_setup_file_associations();
void platform_remove_file_associations();
bool platform_setup_uri_protocol();
// This function cannot be marked as 'static', even though it may seem to be,
// as it requires external linkage, which 'static' prevents
__declspec(dllexport) sint32 StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, sint32 nCmdShow);

View File

@@ -1040,7 +1040,8 @@ utf8* platform_get_username() {
// File association setup
///////////////////////////////////////////////////////////////////////////////
#define SOFTWARE_CLASSES L"Software\\Classes"
#define SOFTWARE_CLASSES L"Software\\Classes"
#define MUI_CACHE L"Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache"
static void get_progIdName(wchar_t *dst, const utf8 *extension)
{
@@ -1183,4 +1184,50 @@ void platform_remove_file_associations()
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// URI protocol association setup
///////////////////////////////////////////////////////////////////////////////
bool platform_setup_uri_protocol()
{
log_verbose("Setting up URI protocol...");
// [HKEY_CURRENT_USER\Software\Classes]
HKEY hRootKey;
if (RegOpenKeyW(HKEY_CURRENT_USER, SOFTWARE_CLASSES, &hRootKey) == ERROR_SUCCESS) {
// [hRootKey\openrct2]
HKEY hClassKey;
if (RegCreateKeyA(hRootKey, "openrct2", &hClassKey) == ERROR_SUCCESS) {
if (RegSetValueA(hClassKey, NULL, REG_SZ, "URL:openrct2", 0) == ERROR_SUCCESS) {
if (RegSetKeyValueA(hClassKey, NULL, "URL Protocol", REG_SZ, "", 0) == ERROR_SUCCESS) {
// [hRootKey\openrct2\shell\open\command]
wchar_t exePath[MAX_PATH];
GetModuleFileNameW(NULL, exePath, MAX_PATH);
wchar_t buffer[512];
swprintf_s(buffer, sizeof(buffer), L"\"%s\" handle-uri \"%%1\"", exePath);
if (RegSetValueW(hClassKey, L"shell\\open\\command", REG_SZ, buffer, 0) == ERROR_SUCCESS) {
// Not compulsory, but gives the application a nicer name
// [HKEY_CURRENT_USER\SOFTWARE\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache]
HKEY hMuiCacheKey;
if (RegCreateKeyW(hRootKey, MUI_CACHE, &hMuiCacheKey) == ERROR_SUCCESS) {
swprintf_s(buffer, sizeof(buffer), L"%s.FriendlyAppName", exePath);
RegSetKeyValueW(hMuiCacheKey, NULL, buffer, REG_SZ, L"OpenRCT2", sizeof(L"OpenRCT2") + 1);
}
log_verbose("URI protocol setup successful");
return true;
}
}
}
}
}
log_verbose("URI protocol setup failed");
return false;
}
///////////////////////////////////////////////////////////////////////////////
#endif