Shell Navigation URLs (Modding)

From Socially Distant Manual

When writing a mod for Socially Distant, you may need to tell the game's user interface to navigate to a certain screen or to perform a certain action. While it is relatively trivial to use the game's C# API to do this with a Script Mod, you may not have access to the C# API in certain cases such as writing a mission script or making a Content Mod. Shell Navigation URLs are a system that let you navigate through the UI when C# isn't available to you.

Using Shell Navigation URLs

There are three ways to use Shell Navigation URLs depending on your situation.

Via the C# API

Even if you have access to C#, you may find it more convenient to use navigation URLs in certain circumstances - such as opening an in-game website. This would be useful when the C# way of accomplishing the task would be too verbose.

You can use the IUriManager API to execute a Shell Navigation URL. You can access it through the IGameContextAPI which is accessible via your GameModule class through the Context property.

The following code shows how a Script Mod can open the Mailbox when the desktop is first started.

public sealed class MyScriptMod : GameModule
{
    public override void OnGameModeChanged(GameMode gameMode)
    {
        if (gameMode != GameMode.OnDesktop
            return;
            
        // Build the URI "shell://tool/mailbox"
        var uriBuilder = new UriBuilder
        {
	        Scheme = "shell",
	        Host = "tool",
	        Path = "/mailbox"
        };
        
        // Execute the navigation URL
        Context.UriManager.ExecuteNavigationUri(uriBuilder.Uri);
    }
}

Note: If you attempt to execute a Navigation URL with an unrecognized Scheme, you will get an InvalidOperationException from the game. You can use the IUriManager.IsSchemeRegistered() API to check if a given scheme name is registered.

Via TextMeshPro markup

You can create clickble Navigation URL links in the game's UI by using TextMeshPro markup in any place where TextMeshPro markup is supported by the game. This includes Info Panel widgets, chat messages, settings pages and emails - but that is in no way an exhaustive list.

To do this, use the standard <linl>tag like so:

This is a <link="shell://tool/terminal">clickable link that opens the Terminal!</link>

If an invalid link is provided in the markup,, the game will log an error to the game log. It will also present an error message to the player in a dialog box. You can use the dmesg xommand in the Terminal to see what went wrong.

This method is useful when adding new websites to the in-game Internet, since it can be used to link pages together via web:// URLs.

Via sdsh scripts

Any sdsh script executed at runtime (mission scripts, chat conversations, etc.) as part of gameplay can execute Shell Navigation URLs directly via the shellexec command. Below is an example of a hypothetical tutorial mission that opens the Terminal when started.

#!mis_tutorial_example

metadata() {
    name "Example Mission"
    giver chr_example
    type main
    start_type scripted
}

start() {
    shellexec shell://tool/terminal
}

You can use the exit code of the shellexec command to determine whether the navigation was successful and what went wrong.

  • Exit code 0: Success
  • Exit code 1: Navigation ERror - Check Game Log
  • Exit Code 2: Invalid URL Scheme
  • Exit Code 3: URL Parse Error

Note that a failed hellexec navigation request will not halt the sdsh script.

Custom URL Schemes

While the game has many built-in schemes such as web:// and shell:// for interacting with the base game's UI, some mod developers may wish to handle custom schemes specific to their mod. You must implement a Script Mod to do this.

To create a custom scheme handler, start by creating a class that implements the IUriSchemeHandler interface.

public sealed class MyCustomSchemeHandler : IUriSchemeHandler
{
    /// <inheritdoc />
    public void HandleUri(Uri uri)
    {
        if (uri.Host == "test")
        {
            Debug.Log("This is a test!");
        }
    }
}

You can then register the custom scheme handler with the IUriManager like so:

Context.UriManager.RegisterSchemeHandler("example", new MyExampleSchemeHandler());

You will need to unregister the scheme handler before your mod is unloaded. You can do so like this:

Context.UriManager.UnregisterSchemeHandler("example");

Note: You will crash with an InvalidOperationException if you do any of the following:

  • register a scheme name that's already been registered somewhere else
  • unregister a scheme name that isn't yet registered
  • register a scheme name that someone else is about to register later on

You cannot register more than one scheme handler for a given scheme name, snce it would be impossible for the game to know which handler to use.

Built-In URLs

This section shows built-in URLs the game supports, and how to use them.

Web URLs (web://)

These URLs map to in-game websites in the Web Browser. You can navigate to any in-game website and look at the address bar. The URL displayed in the address bar is the same one used to navigate to that page via Shell Navigation URLs.

For example, you can navigate to the game's social media news feed by navigating to web://flock.social/. Or you can navigate to a specific user profile with web://flock.social/username.

Web URLs work the exact same way as HTTP URLs in real life.

Missions (mission://)

You can use mission://start/<missionID> to start a given mission.

You can use mission://abandon to abandon the current mission, if any, and if possible.

Desktop Navigation (shell://)

This scheme is only available while a game is active and the desktop is visible on-screen (during GameMode.OnDesktop). Attempts to use these URLs outside of that game mode will crash the game.

You can switch between primary tools using shell://tool/toolname . The following ones are supported by default:

  • shell://tool/terminal - switch to the Terminal
  • shell://tool/mailbox - switch to the mailbox
  • shell://tool/web - switch to the Web Browser
  • shell://tool/chat - switch to chat

You can interact with the currently active tool's tab list with the following URLs:

  • shell://tab/open - Opens a new tab if the current tool supports multiple tabs.
  • shell://tab/close - Closes the current tab, if a tool is currently active. If there's only one tab open, the entire tool will close.
  • shell://tab/<number> - Switch to the numberth tab in the current tool. The game will clamp number to between 0 (the first tab) and the number of open tabs minus 1 (the last tab).
  • shell://tab/next - Go to the next tab (will wrap to the first tab)
  • shell://tab/previous - Go to the previous tab (will wrap to the last tab)
  • shell://tab/first - Go to the first tab
  • shell://tab/last - Go to the last tab

You can show, hide, and toggle certain desktop elements with shell://show/<element>, shell://hide/<element> and shell://toggle/<element> - Valid element names are:

  • network - The Network View tile
  • desktop - Equivalent of the "Show Desktop" dock icon
  • infopanel - The Info Panel on the right side of the screen
  • applications - The "Applications" window for launching floating apps
  • city - The City Map
  • playeroverlay - The player's stats, the menu that appears when clicking the player's username in the Status Panel.
  • notifications - The Notifications dropdown in the Status Panel

City Map (city://)

You can tell the game to navigate to a specific spot on the city map when the desktop is visible.

  • city://district/<district_name> - Focus on a specific district of the City.
  • city://waypoint/<waypoint_id> - Focus on a specific waypoint on the map (such as a business).
  • city://network/<host> - Focus on a specific public network located within the city.

Network View (net://)

You can use the net:// scheme to control what LAN the Network View tile shows.

  • net://player - Show the player's own network
  • net://<public_host> - Show the LAN of a non-player network. You can use a Narrative Identifier, Domain Name, or Public IP address.

In both cases, you can use the path part of the URL to select a specific device in the network once the network is visible. Doing so will cause the player to discover the device as if they'd scanned it with nmap. Just like with networks, you can use Narrative IDs, device hostnames and device IP addresses.

  • net://player/playerdevice - select the player's own computer (playerdevice is the Narrative ID of the player's PC.)
  • net://moneybank.com/online_banking_01 - select device with host online_banking_01 on the moneybank.comnetwork
  • net://204.31.188.26/192.168.1.3 - select a device based on local IP address on a network with the given public IP address

Note that you can also mix and match what kind of identifier you use for the network and device, e.g using Narrative ID to find the network but hostname to find the device.

Because there may be ambiguity between a Narrative ID and a host/domain name, the game will always prioritize a Narrative ID when available. To avoid this causing problems for you, it is a good practice to prefix all Narrative IDs with net_ for networks and dev_ for devices. Only the player's network and device is an exception to this rule.

If you attempt to view a network that doesn't exist in the world, the game will silently ignore the request. This is also the case for devices.

When navigating to a network, the game will open a new tab in the Network View for it. If the network is already open in another tab, the game will instead switch to it. The player can close any tabs for non-player networks.

Mailboxes (mailbox://)

You can navigate to a specific user's mailbox via the mailbox://<user> scheme. This is useful when the player has successfully hacked into a user's email address.

You can use either a Narrative Identifier or a character username to identify which person's mailbox the game should open. Using player will always open the player's own mailbox. Each mailbox is opened in a new tab in the Mail Viewer.

You can use the path part of the URL to specify an additional Narrative Identifier of a specific email to view. The email must either be from or to the user whose mailbox you're trying to view.

It is a good practice to prefix user narrative identifiers with chr_ to prevent them from clashing with actual usernames.

Chat Conversations (chat://)

You can navigate to specific chat conversations with chat:// URLs.

  • chat://player/dms - Navigate to the player's Direct Messages list
  • chat://player/dm/<user> - Navigate to a specific DM with a given user, by username or narrative ID.
  • chat://player/<guild> - Navigate to a given guild (server) based on Narrative Identifier or guild ID. If the player isn't in the guild already, they will be added to it.
  • chat://player/<guild>/<channel> - Navigate to a specific channel (by narrative ID or channel name) in a guild.

You can also open another user's chat environment via chat://<user> where the user is specified by username or narrative identifier. All the same paths work, however the user will not be joined to new guilds.

When navigating to a conversation as a non-player user, the chat will be read-only. Only players can send messages in a given channel since the game's dialogue system can only receive dialogue choices from a player.

System Settings (settings://)

You can open System Settings to a specific settings page with settings://<page_id>, and can scroll to a specific setting with settings://<page_id>/<setting_id>. This is rarely useful, but can be used to link to different settings in the game's UI.

Game Control (system://)

You can perform certain game control actions using the system:// scheme.

  • system://quit - Quit the game completely (exit to host desktop) with confirmation from the player.
  • system://logout - Log out of the current session if in a game.
  • system://login/<save_file_id> - Log in to a specific save file by file ID. Will require a log out if already in-game.
  • system://new_user - Create a new user (open the Character Creator). Requires a logout if already in-game.
  • system://settings - Open System Settings, but don't navigate to a specific page or setting.
  • system://open/<location> - Open a location within the game's data directory on the host.
    • saves - Open the saves directory
    • saves/<save_file_id> - Open a specific save file
    • mods - Open the mods directory
    • screenshots - Open the screenshots directory
    • installation - Open the game's executable installation directory
    • logs - Open the logs directory
    • userdata - Open the user data directory itself, where many of the above locations are stored.
  • system://panic - If something has gone irrepairably, horrifically wrong, use this to raise a system panic so the player knows what happened. This force-ends the current game if any, and tells the user to either quit the game or view logs.