Skip to content

API Reference

DooDesch edited this page Jun 23, 2026 · 9 revisions

API Reference

For mods that want to appear as a gamemode in Side Hustle's main-menu list. Register early (in your OnInitializeMelon); registration is load-order independent, so it does not matter whether Side Hustle or your mod loads first.

Setting up the project

Reference SideHustle.dll and declare it as an optional dependency, so the hub loads first and your mod still loads cleanly if Side Hustle is absent:

[assembly: MelonOptionalDependencies("SideHustle")]

Reference these from a normal modded install:

  • Mods/SideHustle.dll - the API
  • MelonLoader/net6/MelonLoader.dll, Il2CppInterop.Runtime.dll
  • UnityEngine.CoreModule.dll etc. only if your own gamemode needs them
  • For Thunderstore, list DooDesch-SideHustle as a dependency.

SideHustle.API

namespace SideHustle
{
    public static class API
    {
        // Register (or replace, by Id) a gamemode.
        public static void Register(GamemodeDescriptor descriptor);

        // Remove a previously registered gamemode. Returns true if one was removed.
        public static bool Unregister(string id);

        // True once Side Hustle's own OnInitializeMelon has run.
        public static bool IsReady { get; }

        // The currently registered gamemodes.
        public static IReadOnlyList<GamemodeDescriptor> Registered { get; }
    }
}

Registering with an existing Id replaces it, so re-registering (hot reload, double init) is safe.

GamemodeDescriptor

Field Meaning
Id Stable, unique id (e.g. "you.yourmode"). Required. Used for de-dup and lobby filtering.
DisplayName Shown in the list (falls back to Id).
Description One-line description under the name.
Author Shown in the list (optional).
Icon / IconTex Optional Sprite / Texture2D for the list row. If Icon is null, the hub builds one from IconTex.
Support Singleplayer | Multiplayer | Hybrid - decides whether selecting launches straight into SP or shows Singleplayer / Host / Join.
Surface MenuSpace (overlay on the menu, no save) | World (Side Hustle boots a throwaway save first).
OnLaunchSingleplayer Action<LaunchContext> - start singleplayer. Required for Singleplayer / Hybrid.
OnHostMultiplayer Optional - start hosting a multiplayer session.
OnJoinMultiplayer Optional - join a multiplayer session.
OnExitToHub Optional - called when Side Hustle tears the gamemode down (the player backs out).

Helper properties: AllowsSingleplayer and AllowsMultiplayer derive from Support.

LaunchContext

Passed to your launch callbacks.

Member Meaning
Descriptor The descriptor being launched.
IsHost true = host, false = client, null = singleplayer.
LobbyId Steam lobby id for multiplayer; 0 for singleplayer.
IsSingleplayer true when this is a singleplayer launch (IsHost == null).
ReturnToHub() Call when your gamemode finishes; the hub restores the menu and re-shows the list. Safe to call once.

Enums

public enum GamemodeSupport { Singleplayer, Multiplayer, Hybrid }
public enum GamemodeSurface { MenuSpace, World }
  • MenuSpace gamemodes build their own overlay on top of the main menu and never load a save (e.g. an in-game editor).
  • World gamemodes need the loaded game world, so Side Hustle boots a throwaway save before handing over.

When to register (important)

Register early - in your OnInitializeMelon. The menu list is built from the live registry each time the menu scene loads, so a gamemode registered before the first menu shows up immediately. Registering later is fine too; it appears the next time the menu is opened.

Minimal example

using SideHustle;
using MelonLoader;

[assembly: MelonOptionalDependencies("SideHustle")]

public sealed class Core : MelonMod
{
    public override void OnInitializeMelon()
    {
        SideHustle.API.Register(new GamemodeDescriptor
        {
            Id = "you.yourmode",
            DisplayName = "Your Mode",
            Description = "What your gamemode does.",
            Author = "You",
            Support = GamemodeSupport.Singleplayer,
            Surface = GamemodeSurface.MenuSpace,
            OnLaunchSingleplayer = ctx =>
            {
                // build your overlay / start your mode
                // when finished: ctx.ReturnToHub();
            }
        });
    }
}

Clone this wiki locally