Skip to content

Your first mod ​

This mod adds a free controller based on the game's Constant part.

1. Create the project ​

Create a folder containing:

text
MyFirstMod/
  MyFirstMod.csproj
  Local.props
  Plugin.cs

Use this MyFirstMod.csproj:

xml
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.1</TargetFramework>
    <LangVersion>latest</LangVersion>
    <Nullable>disable</Nullable>
    <AssemblyName>MyFirstMod</AssemblyName>
  </PropertyGroup>

  <Import Project="Local.props" Condition="Exists('Local.props')" />

  <PropertyGroup>
    <ManagedPath Condition="'$(ManagedPath)' == ''">$(GamePath)/StellarDrive_Data/Managed</ManagedPath>
    <LoaderPath Condition="'$(LoaderPath)' == ''">$(GamePath)/MelonLoader/net35</LoaderPath>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="StellarStriderLib" Version="1.5.1" ExcludeAssets="runtime" />
    <Reference Include="MelonLoader"><HintPath>$(LoaderPath)/MelonLoader.dll</HintPath><Private>false</Private></Reference>
    <Reference Include="UnityEngine.CoreModule"><HintPath>$(ManagedPath)/UnityEngine.CoreModule.dll</HintPath><Private>false</Private></Reference>
    <Reference Include="Ships.Interface"><HintPath>$(ManagedPath)/Ships.Interface.dll</HintPath><Private>false</Private></Reference>
    <Reference Include="Ships"><HintPath>$(ManagedPath)/Ships.dll</HintPath><Private>false</Private></Reference>
    <Reference Include="Items.Model"><HintPath>$(ManagedPath)/Items.Model.dll</HintPath><Private>false</Private></Reference>
    <Reference Include="Research.Interface"><HintPath>$(ManagedPath)/Research.Interface.dll</HintPath><Private>false</Private></Reference>
    <Reference Include="Newtonsoft.Json"><HintPath>$(ManagedPath)/Newtonsoft.Json.dll</HintPath><Private>false</Private></Reference>
  </ItemGroup>

  <Target Name="ValidateReferences" BeforeTargets="ResolveAssemblyReferences">
    <Error Condition="!Exists('$(LoaderPath)/MelonLoader.dll')"
           Text="Set GamePath or LoaderPath to your MelonLoader installation." />
    <Error Condition="!Exists('$(ManagedPath)/UnityEngine.CoreModule.dll')"
           Text="Set GamePath or ManagedPath to the game's managed assemblies." />
  </Target>
</Project>

NuGet supplies SSLib. The other references come from your game installation. ExcludeAssets="runtime" and Private=false prevent dependency DLLs from being copied to your output.

2. Set your game path ​

Create Local.props and set the path to your game:

xml
<Project>
  <PropertyGroup>
    <GamePath>C:/Program Files (x86)/Steam/steamapps/common/StellarDrive Demo</GamePath>
  </PropertyGroup>
</Project>

If your installation uses different assembly locations, also set ManagedPath or LoaderPath. Keep this file out of source control.

3. Add the plugin ​

Use this Plugin.cs:

csharp
using System;
using MelonLoader;
using StellarStriderLib;

[assembly: MelonInfo(typeof(MyFirstMod.Plugin), "My First Mod", "1.0.0", "YourName")]
[assembly: MelonGame("CuriousOwlGames", "StellarDrive")]
[assembly: MelonAdditionalDependencies("StellarStriderLib")]

namespace MyFirstMod
{
    public sealed class Plugin : MelonMod
    {
        public override void OnInitializeMelon()
        {
            var content = StriderRegistry.Create("example.firstmod", typeof(Plugin).Assembly);

            content.RegisterCategory(new CategoryDefinition
            {
                Id = "parts",
                Name = "My First Mod",
                SortOrder = 100
            });

            content.RegisterPart(new PartDefinition
            {
                Id = "controller",
                Name = "First Controller",
                Description = "My first SSLib part, based on the native Constant.",
                Donor = "Constant",
                Category = "parts",
                BuildingCost = Array.Empty<ItemCost>()
            });

            content.RegisterResearchTree(new ResearchTreeDefinition
            {
                Id = "technology",
                Nodes = new[]
                {
                    new ResearchNodeDefinition
                    {
                        Id = "basics",
                        Name = "First Mod Basics",
                        UnlockedParts = new[]
                        {
                            PartRef.Mod(content.Key("controller"))
                        }
                    }
                }
            });

            MelonLogger.Msg("My First Mod content registered.");
        }
    }
}

The plugin registers a category, a free part, and a free research unlock. The part keeps the donor's model, sockets, and input editing.

Register content once during OnInitializeMelon. Keep example.firstmod and released local IDs stable; display names can change. AllowMove defaults to false, so pickup/move is disabled while normal use still works.

StellarStriderLib documentation · Mods for StellarDrive