Mod Creation - Getting Started

NeptuneSky

Modder
TEAM HAWK
Swingin' on a Star
Atlas
Under Pressure
Registered
#1
Welcome to the entry-level tutorial for modding. If you are here, you are probably wondering where to get started. This thread will go over all of the basics. How to set up a project, what tools you need, where to find information, etc. I should note this tutorial is Windows exclusive to minimize confusion.

There's a lot to cover, so let's dive on in!


Tools:

dnSpy or ILSpy - Opens DLL files. Spaceflight Simulator_Data/Managed/Assembly-CSharp.dll is where you will find the game's compiled code. ILSpy has a much better decompiler than dnSpy, but you may find dnSpy has a more appealing interface. If you wish to use dnSpy, it's advised you still also get ILSpy in case you come upon broken-looking code and get confused. dnSpy can also directly edit the game's code without the use of Harmony patches (which will be shown later), you can use this to test changes quickly without having to build your mod every time, though it's not advised.

Visual Studio - This allows you to make your own mod DLL's. Community Edition is free. Get .NET desktop development from the installer.

Github Desktop - Github is an invaluable source for making collaborations easy as well as helping to keep your mods transparent. Github Desktop helps you to easily push and pull changes to your project, however you have to use the website to make a downloadable release as well as to make a new account.

Getting Started:

Now that you have the tools you need, you can start creating. You will need to have at least a basic understanding of C#, Unity, and how to read code before you start, as you will be interacting with the game's code.

Open Visual Studio and create a new project. Change the language to C# and choose "Class Library (.NET Framework)". Check "Place project and solution in the same directory" and use .NET Framework 4.8.

Go to the "Git" tab and follow the instructions to create a new repository for your mod. Now, open Github Desktop and go to File > Add local repository > Choose...

Navigate to where you set your repositories to be saved, open the folder for your mod, then select the folder. You can now easily save your code to the repository, called committing, and pull changes made by others if you are doing a collaboration. You will want to push your code to the repository whenever you make a new release, or just periodically as you add new things. Changes will automatically be shown in the side bar, and you can chose what you want to commit.

Open Visual Studio. Right-click your project name in the side bar, then go to Add... > Reference. Navigate to your SFS Steam files, then go to Data\Managed. Select 0Harmony.dll,Assembly-CSharp.dll, UnityEngine.dll, UnityEngine.UI.dll, UnityEngine.TextRenderingModule.dll, and UnityEngine.CoreModule.dll.
These references allow you to use all the libraries you need and hook into the game's code.

For the mod loader to get your mod, it will need an "entry point", meaning the main class that tells the loader what to do when it loads and where to get the details of your mod such as name, version, latest supported game version, etc.

C#:
using HarmonyLib;
using ModLoader;
using ModLoader.Helpers;

namespace YourProjectName
{
    public class Main : Mod
    {

        public override string ModNameID => "ExampleID";
        public override string DisplayName => "foo";
        public override string Author => "bar";
        public override string MinimumGameVersionNecessary => "1.5.9.8";
        public override string ModVersion => "v1.0.0";
        public override string Description => "Insert description here";

        // This initializes the patcher. This is required if you use any Harmony patches.
        static Harmony patcher;

        public override void Load()
        {
            // This tells the loader what to run when your mod is loaded.
        }

        public override void Early_Load()
        {
            // This method runs before anything from the game is loaded. This is where you should apply your patches, as shown below.

            // The patcher uses an ID formatted like a web domain.
            patcher = new Harmony("example.foo.bar");

            // This pulls your Harmony patches from everywhere in the namespace and applies them.
            patcher.PatchAll();
        }
    }
}
If you want to place a window with text, buttons, etc. on the screen you will need to make a new class. Here you will use the game's built-in mod GUI system.

C#:
using SFS.UI;
using SFS.UI.ModGUI;
using UnityEngine;
using Type = SFS.UI.ModGUI.Type;

namespace YourProjectName
{
    public class NewClass
    {
        // Create a GameObject for your window to attach to.
        static GameObject windowHolder;

        // Random window ID to avoid conflicts with other mods.
        static readonly int MainWindowID = Builder.GetRandomID();

        static Window window;
        static RectInt windowRect = new RectInt(0, 0, 300, 150); // x-position, y-position, width, height
        /*
        Call this method when you want to show your UI.
        */
        public static void ShowGUI()
        {
            // Create the window holder, attach it to the currently active scene so it's removed when the scene changes.
            windowHolder = Builder.CreateHolder(Builder.SceneToAttach.CurrentScene, "MyHolderName");

            window = Builder.CreateWindow(windowHolder.transform, MainWindowID, windowRect.width, windowRect.height, windowRect.x, windowRect.y, true, true, 0.95f, "My Window");

            // Create a layout group for the window. This will tell the GUI builder how it should position elements of your UI.
            window.CreateLayoutGroup(Type.Vertical);

            Builder.CreateButtonWithLabel(window, 290, 50, 0, 0, "Button Label", "Button Text", ButtonMethod);
        }

        /*
        Method to pass into the button element to give it functionality
        */
        static void ButtonMethod()
        {
            MsgDrawer.main.Log("Hello world");
        }
    }
}
You can create more than just a button, you can just type Builder.Create and Visual Studio's auto-fill should show you all the UI elements you can create. There are currently no docs on these, so it is advisable to look at other existing mods that make use of it for inspiration.

Now, you will need to tell the game to show your GUI when the correct scene loads. For this example we will use the build scene.

C#:
public override Load()
{
    /*
    The below formatting is called a "lambda" method, it allows you to define a method in place of where
    a pre-defined method would be accepted as a parameter. It is useful in this case because you can use it
    to make it call more than one method without repeatedly adding to OnBuildSceneLoaded.
    */
    SceneHelper.OnBuildSceneLoaded += () =>
    {
        NewClass.ShowGUI();
    };
}
To give your code and UI elements any functionality, you will have to use Harmony patches, which edit a method in the vanilla code. To do this, you will first need to find what you want to change within the vanilla code. Open dnSpy or ILSpy. go to File > Open, then navigate to Spaceflight Simulator_Data\Managed\Assembly-CSharp.dll and open it. You can now scroll through the game's source code to find what you'd like to edit, or you can use the search tool to enter various key words to try and narrow down what you want.

To edit the code, you can usually use Harmony prefixes or postfixes. These are very powerful in it of themselves, they can directly interact with the arguments that go into the method as well as change what the method outputs, and also allows you to run your own custom code before or after the method.

However, if you run into a situation where you absolutely cannot do what you are trying to do without directly editing the method's code, you will need to use a transpiler, but they are very advanced and involve manipulating raw assembly code. You should generally try to make any functions make use of prefixes and postfixes. You can also use a prefix to completely skip the method's original code and use your own custom code, but this isn't advisable as it can break compatibility with other mods.

You can find documentation about Harmony patches here.

Once you have what you'd like to change, you will need to make note of the namespace, class name, and method name. Now, make a new class for your patch.

C#:
using HarmonyLib;
using UnityEngine;
using System;
// Replace SFS.Namespace with the namespace of the code you'd like to change.
using SFS.Namespace

namespace YourProjectName
{
    [HarmonyPatch(typeof(OriginalClassName), "OriginalMethodName")]
    public class MyPatch
    {
        [HarmonyPrefix]
        public static (insert return type here) Prefix()
        {
            // Code will run before the original method.
        }

        [HarmonyPostfix]
        public static void Postfix()
        {
            // Code will run after the original method. This will run regardless of if the original method or your prefix has a return.
        }
    }
}
And that's it for making your mods! To test them, you will just need to build your mod then copy it to the game's Mods folder.

Open Visual Studio then press Ctrl+B. It will tell you at the bottom if the build was successful.

Once you do that, open your file explorer and navigate to where you stored the repository, then go to Bin\Debug and look for the .dll file with your project's name. Copy it, then navigate to the SFS mod folder. Place the mod inside. You can now use the F1 key in-game to open and close the console to see if your code throws any errors you need to fix.

Each time you build a new version, you can now just overwrite the old file with the new one.

Releasing Your Mod:

Now that you've made your mod, it's time to release it publicly. Navigate to GitHub and sign in, then open your repository. Click Releases on the right, then click Draft a new release. Find your mod's folder in your game files. Drag and drop the .dll file from your file explorer to the GitHub draft. Follow the instructions to create the release, then you are done! You've now released the first version of your mod.


And that's it! This tutorial will be updated with time, as new mod loader versions come out and new tools/information surface.

Thank you for reading, and I hope this helps.
 
Last edited:

NeptuneSky

Modder
TEAM HAWK
Swingin' on a Star
Atlas
Under Pressure
Registered
#2
Good Modding Practices:

Once you get into a rhythm and learn enough to start making mods for a public release, there are several good practices you should adhere to to make your mods look professional and to ensure that they don't cause issues when paired with others. This section will detail some of them.

1. Don't make immovable windows. This is an easy way to have your mod cause conflicts. There is no easy way of getting the window positions for other mods to automatically position yours. If you have an immovable window overlapping another mod's window, it will make the other's inaccessible or hard to read. Allowing your window to be movable also allows the player to customize where they want all their windows to be on the screen, as it can get messy. The example above already has window dragging enabled.

2. Fix your errors, and make use of alpha/beta labeling. Don't make a full release of a mod if you know there are errors with it. Also, if you find an error relating to something you've patched or relating to your mod, you should fix them. Letting errors pile up in the console, even if your mod still technically works, is bad practice. Make good use of alpha/beta labeling if you know the version of mod you are releasing isn't stable.

3. Make a thorough guide for using your mod, or keep it simple. Not everyone is going to understand your specific practices for how to show windows or making use of the mod's functions. Add a list of keybinds and a how-to somewhere in your release post, or make your mod extremely intuitive so anyone can use it.
 
Last edited:

N2O4

Modder
Swingin' on a Star
Atlas
Biker Mice from Mars
ET phone home
Voyager Quest
Floater
Registered
#4
Can you make a video about this tutorial?
In this way, everyone learns more easily.
Well, he is already learning new modloader, and as old modloader is gonna be useless in a few weeks, there is no point in making tutorials about it.
 

Altaïr

Space Stig, Master of gravity
Staff member
Head Moderator
Team Kolibri
Modder
TEAM HAWK
Atlas
Deja Vu
Under Pressure
Forum Legend
#5
Can you make a video about this tutorial?
In this way, everyone learns more easily.
He already made a great effort making this thread. If you are interested into modding you would have to spend some time on it, it requires patience and concentration you know. There are many things in practice that can't be covered by a "simple" video.
 

Altaïr

Space Stig, Master of gravity
Staff member
Head Moderator
Team Kolibri
Modder
TEAM HAWK
Atlas
Deja Vu
Under Pressure
Forum Legend
#7
I cant find the Modloader.dll file in Managed
Carter needs to update his thread :)

There's no more modloader.dll file, you can just ignore this. That was written for Dani's mod loader who provided his own dll, but now the mod loader is included in the Assembly-CSharp.dll, so referencing that one is enough.
 

NeptuneSky

Modder
TEAM HAWK
Swingin' on a Star
Atlas
Under Pressure
Registered
#8
Thread updated. Information here is now relevant to official modloader.
 

CosmauNox

Man on the Moon
Registered
#9
So is hacking in C# the only way to mod? No extern C APi, or any sort of API?
I want to add Lua as a way to code and mod without having to recompile, as well as being a much more robust way of developing mods, than hacking an exe/dll, even if it's managed code, even little updates to SFS are going to break stuff.....
Still going to give it a try,
Thx for the intro
 

NeptuneSky

Modder
TEAM HAWK
Swingin' on a Star
Atlas
Under Pressure
Registered
#10
So is hacking in C# the only way to mod? No extern C APi, or any sort of API?
I want to add Lua as a way to code and mod without having to recompile, as well as being a much more robust way of developing mods, than hacking an exe/dll, even if it's managed code, even little updates to SFS are going to break stuff.....
Still going to give it a try,
Thx for the intro
No API. You use harmony patches in C# as shown. Yes little updates can break things but having to maintain an API would be more work for the devs, and not really worth the hassle when they can just implement harmony and have really easy mod support, and just rely on the modders to fix their stuff on the off chance something they make gets affected and breaks.

It's not the ideal solution for modders, but it is what it is. Atleast we get an official modloader and mod gui system, so can't complain too much. Also you're not recompiling the game with this method, you just need dnSpy or ILSpy to look at the game's code, then you are compiling your own separate mod dll that uses patches that are loaded at runtime. You can read about Harmony in the docs link i provided.
 
Last edited:

Altaïr

Space Stig, Master of gravity
Staff member
Head Moderator
Team Kolibri
Modder
TEAM HAWK
Atlas
Deja Vu
Under Pressure
Forum Legend
#15
oh? didnt know, and also, dont really understand what events do what and how to do that and that you know?
It will be hard to answer such a vague question... First of all that tutorial supposes that you have at least some basic understanding of C# and some general coding knowledge. If it's not the case you'll have to familiarize yourself with the basics. And of course you'll have to read the Harmony doc too.
Then you can take as an example the code from other modders. There are many mods now, and we generally make our code available through Github, this is a very good source of examples.
 

Noor Nehan

Biker Mice from Mars
ET phone home
Voyager Quest
Floater
Registered
#16
How Can I make custom parts? It would be really helpful with a detailed instructions. I'm kinda beginner in the world of modding. It would be really helpful.