Optional Dependencies
How does one go about implementing support for optional dependencies?
With c++ code, I assume I can't import header files from said mod, as that wouldn't work if it doesn't exist.
If this is the case, how can I go about editing some value on some object from that mod, if I can't import any type data for the mod?
Are preprocessor directive the way to do this? If so what do I to test if a mod exists with them?
41 Replies
1. UE reflection
2. conditionally-loaded C++ modules
Any links to docs I can look into?
Not that I can think of at the moment
They're not Satisfactory-specific concepts so try looking in general UE stuff. Maybe look at plugins, they might do stuff like that
all good. I do some googling... ...tomorrow
Importing Another Mod :: Satisfactory Modding Documentation
The modding documentation requires time to update and can only cover so much. Looking at other mods' source code is a great way to expand yo...
that's the most docs we have on it
This is not so much about importing another mod, but rather making it an optional dependency
For C++ stuff you can make another module that is only loaded if the dependencies are met
But you can also do it in blueprints with a life cycle event. I remember more details on it https://docs.ficsit.app/satisfactory-modding/latest/Development/ModLoader/ModModules.html touches on it but I think @Robb (Busy) might know more?
Ah yes, you can also do stuff like that
But what I'm not sure is how to deal with stuff on the BP side
AFAIK the blueprint links wont be engaged if the content isn't loaded and we use an asset registry that the items have to reference themselves with. which is why a conditional module load is fine so long as you properly firewalled the content. Nothing satops you form CDO'ing your own content to integrate it better with optional content.
It depends on what you are trying to do differently when that optional dependency is present, and if it's implemented in BP or cpp
If you need a new cpp data structure that the other mod adds, I'm not sure how
If it's blueprint then the mod loading library, separate mod modules, soft class paths, and cdo edits are your friends
Separate mod modules works for C++ stuff
as in C++ implemented mod module, or cpp module
Want to make sure I'm following the terms
Oh, sorry, got confused there
I mean C++ modules, not SML's mod modules
conditionally-loaded C++ moduleI tried this approach but it seems if I statically reference another mod, that mod has to be present even if I never load the module that makes said reference. (Or I'm somehow loading the module without knowing) I tried wrapping the the
#include
in THIRD_PARTY_INCLUDES_START
and
THIRD_PARTY_INCLUDES_END
but the error persistedNo, that's not a conditionally-loaded C++ module
In the .uplugin you should have two modules, the first one is your default C++ module and the other one should be the one with dependencies
(this is just an example of having 2 C++ modules, I just woke up)
Is there any examples I can look at?
Not that come to mind
Other than looking at engine plugins
This is what i'm trying to do here:
https://docs.ficsit.app/satisfactory-modding/latest/Development/ModLoader/ModModules.html#:~:text=The%20root%20Mod,won%E2%80%99t%20be%20registered).
Mod Modules :: Satisfactory Modding Documentation
Mod Modules are a system provided by SML that allows for simple hooking into the engine life-cycle at key locations important for Satisfacto...
That's not what I'm referring to
As a sort of example, the alpakit thing that adds a Cpp module for you only adds one. The Cpp docs walk you through adding another manually
That would be the beginning, yes
Then you have to look into how to specify module dependencies and the like
I kinda have things working. I still need to play around with things a lot more though. Will update later once I've got a bit more working, tomorrow maybe.
Kind of late to all this, but this is how I do it in Digby Tool

Oh right, I forgot you did that thing
Link eater
We have a thing about this in the docs I believe
I think that's the approach Jarno used to add ApCpp but it's definitely not optional
>docsearch third party
This is the best result I got from the SMD :
https://docs.ficsit.app/satisfactory-modding/latest/Development/Cpp/thirdparty.html
Third Party Libraries :: Satisfactory Modding Documentation
Adding third-party Cā+ā+ libaries to your mod is possible but requires some additional setup. The third party library must be included as a ...
Don't have the time to go through and compare the two but I think the Georgy link goes into more detail
What I meant is that both what we have over there in the docs and the Georgy link are about the same thing: adding a 3rd-party library
So I've managed to get things working š
Here's a break down of what I did:
To summarize the problem: I have some c++ code that imports a header file from
FicsitFarming
and I want to run this code only if that mod is present. The rest of the mod should be able to run just fine regardless of if that mod is present or not.
As I'm importing this header file, I can't simply do what @SirDigby {Mod Name} did as the header file import will require the mod to be present regardless of if any code using it is called. To get around this I put all the code that requires the mod to be present in a separate module as suggested by @Rex [they/them]. This module is then only loaded when required.
Note: FicsitFarming
is added to thePrivateDependencyModuleNames
array in BlueBekaTweaksFicsitFarming.Build.cs
so that the header can be found.
To load the module on demand, some c++ code needs to run. This could either be done in my main module file or in one of the root modules, either the GameInstanceModule
or the GameWorldModule
(I'll go with GameWorldModule
for now) - I couldn't figure out how to make a c++ module a root module, so instead I created a c++ parent class for my root modules.
The functions ModuleManager.IsModuleLoaded(DependancyModName)
and ModuleManager.LoadModule(MyDependantModule)
are then used to conditionally load my extra module.
Once the module is loaded, I can then spawn child GameWorldModule
s by first using LoadClass
followed by SpawnChildModule
.Feel free to provide any feedback and ways to improve things, I'd much appreciate it.
@Rex [they/them] I believe you said something about hard coded string being a bad way to do things - what would be the better way in my case?
I couldn't figure out how to make a c++ module a root module, so instead I created a c++ parent class for my root modules.This is one of the few times where doing something in an UObject's constructor is fine:
bRootModule = true;
I believe you said something about hard coded string being a bad way to do things - what would be the better way in my case?You already "hardcode" the
FicsitFarming
string in the .Build.cs
file, so I don't think that's a problem :wonke:
Also, remember that FName
is case-insensitive, but AFAIK mod references are case-sensitive. I would use a regular FString
instead.
Oh, by hardcoding strings, do you mean this?
You should make this a UPROPERTY
in your C++ mod module (which should be UCLASS(Abstract)
), and then set the default value in the BP subclass
Example: https://github.com/Th3Fanbus/ScrewIt/blob/master/Source/ScrewIt/Public/ScrewItRootInstance.h#L80-L85
I don't know if a class reference will work for you. If it doesn't, you can try using a soft class reference insteadI went with
FName
simply because LoadModule
takes an FName
. I could switch to using FString
and only convert to FName
last minute.Oh, LoadModule
Ah, that takes C++ module names
Then don't switch
I confused that
I keep confusing C++ modules with SML mod modules
Thanks for all your help. I wouldn't of been able to come this far without you š
I think mod modules are supposed to be FNames and case insensitive because they correspond to folders on disk. but SMR's mod reference by URL function is case sensitive
I think the
TPromise
and using ModuleManager.OnModulesChanged()
isn't actually necessary and the code can be simplified a bunch.
Correct me if I'm wrong, but the dependency mod will always be loaded before the current mod and thus we don't need to handle the race condition of which mod loads first.
Additionally ModLoadingLibrary->IsModLoaded(ModName)
is probably better than ModuleManager.IsModuleLoaded(ModName)
as the latter will only work for c++ modules.I think using
ModuleManager.IsModuleLoaded(ModuleName)
is the way to go since it checks for C++ plugin modules, which you can link against
That being said, if you only do BP stuff (very likely unless you have the headers for the other mod), it probably won't matter that much